Insert instead of update for history data?

爱⌒轻易说出口 提交于 2019-12-11 20:58:17

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!