In meiner
Session auf der BASTA! 2013 in Mainz habe ich gezeigt, wie man Self-Tracking Entities mit Entity Framework 5+ und den dort standardmäßig verwendeten DbContext entwickeln kann, wenn man nach Database First vorgeht. Leider muss man da ja nun selbst Hand anlegen, zumal Self-Tracking Entities nur für den älteren ObjectContext zur Verfügung stehen. Nachfolgend platziere ich eine kurze Zusammenfassung der notwendigen Schritte. Diese funktionieren auch mit Code Only, sofern man vorsieht, dass die einzelnen Entitäten das nachfolgend vorgeschlagene Interface IEntity implementieren.
1. Interface für Entitäten und State-Enum erstellen
public interface IEntity
{
StateEnum State { get; }
string[] ChangedProperties { get; }
}
public enum StateEnum
{
UnModified = 2,
Added = 4,
Deleted = 8,
Modified = 16
}
2. T4-Template für die Generierung von Entitäten anpassen (fette Ausdrücke ergänzen)
[...]
<#=codeStringGenerator.EntityClassOpening(entity)#>: IEntity
{
public StateEnum State { get; set; }
public string[] ChangedProperties { get; set;}
[...]
3. Helper zum Übernehmen der Stati in den Context erstellen
public class EntityStateHelper
{
public static void SetStates(HotelDbContext ctx)
{
foreach (var entry in ctx.ChangeTracker.Entries())
{
var entity = entry.Entity as IEntity;
entry.State = (EntityState)entity.State;
if (entry.State == EntityState.Modified && entity.ChangedProperties != null)
{
// Die Entität als Unchanged markieren
entry.State = EntityState.Unchanged;
// Nur markierte Properties as Modified markieren
foreach (var propName in entry.CurrentValues.PropertyNames)
{
entry.Property(propName).IsModified = entity.ChangedProperties.Contains(propName);
}
}
}
}
public static void ResetStates(HotelDbContext ctx)
{
foreach (var entry in ctx.ChangeTracker.Entries())
{
var entity = entry.Entity as IEntity;
entity.State = (StateEnum)entry.State;
if (entry.State == EntityState.Unchanged)
{
entity.ChangedProperties = null;
}
}
}
}
4. Anwenden
ctx.Hotel.Attach(h); // Hotel mit Buchungen attachen
EntityStateHelper.SetStates(ctx);
ctx.SaveChanges();
EntityStateHelper.ResetStates(ctx);