问题
I am using EF 6.1 Code First and want to track history data by using a model which (simplified) looks like this:
public class Customer : IHistoryData<CustomerData>
{
public Guid ID { get; set; }
public virtual ISet<CustomerData> Versions { get; set; }
}
public class CustomerData : HistoricalData
{
public string Name { get; set; }
}
public interface IHistoryData<T> where T : HistoricalData
{
ISet<T> Versions { get; set; }
}
public class HistoricalData
{
public int VersionID { get; set; }
public Guid ParentID { get; set; }
public DateTime ValidFrom { get; set; }
public DateTime? ValidUntil { get; set; }
}
They are wired up in the DbContext in the following manner:
modelBuilder.Ignore<HistoricalData>();
modelBuilder.Entity<Customer>().ToTable("Customers").HasMany(c => c.Versions).WithRequired().HasForeignKey(cd => cd.ParentID);
modelBuilder.Entity<CustomerData>().Map(m => m.ToTable("CustomerData")).HasKey(cd => new { cd.VersionID, cd.ParentID });
Now to track different Customer versions, I need to perform an insert instead of an update for changes to CustomerData. For this I hook into SaveChangesAsync()
of DbContext
:
public override Task<int> SaveChangesAsync()
{
foreach (var entry in ChangeTracker.Entries<HistoricalData>().Where(e => e.State == EntityState.Modified))
{
InsertInsteadOfUpdate(entry);
}
return base.SaveChangesAsync();
}
Now I am not sure how to implement InsertInsteadOfUpdate()
, this is my approach so far:
private void InsertInsteadOfUpdate<T>(DbEntityEntry<T> oldEntry) where T : HistoricalData
{
// Get a copy of the modified data
var newEntry = ???
// Modified entry has ended
var originalValues = oldEntry.OriginalValues;
originalValues["ValidUntil"] = DateTime.Now;
oldEntry.CurrentValues.SetValues(originalValues);
// New entry has started
newEntry.ValidFrom = DateTime.Now;
Set<T>().Add(newEntry);
}
However, I have no idea how to get a new copy/clone of the DbEntityEntry<CustomerData>
. And because I both need to modify the "old" entry (to set ValidUntil
) and insert a new entry, I need two different entries.
How would I go about that? Or am I on the wrong track completely?
回答1:
Try this:
DbSet<T> dbSet = Context.Set<T>();
T newEntry = dbSet.Create();
dbSet.Attach(newEntry);
newEntry.CurrentValues.SetValues(oldEntry);
来源:https://stackoverflow.com/questions/22938978/insert-instead-of-update-for-history-data