在SaveChanges中实现历史记录跟踪覆盖

Gre*_*egH 6 c# reflection entity-framework

我目前正试图通过覆盖SaveChanges方法和利用反射,以通用的方式在我的应用程序中的所有表上实现历史记录跟踪.作为一个简单的例子,假设我的域对象有2个类/ dbset,每个类的历史表如下:

DbSet<Cat> Cats { get; set; }
DbSet<CatHistory> CatHistories { get; set; }
DbSet<Dog> Dogs { get; set; }
DbSet<DogHistory> DogHistories { get; set; }
Run Code Online (Sandbox Code Playgroud)

CatHistory类如下所示(DogHistory遵循相同的方案):

public class CatHistory : HistoricalEntity
{
  public int CatId { get; set; }

  public virtual Cat Cat{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的目标是保存对象时,我想在适当的历史记录表中插入记录.使用反射时,我无法克服类型差异.我目前的尝试是在下面,我似乎被困//TODO:在线上:

        var properties = entry.CurrentValues.PropertyNames.Where(x => entry.Property(x).IsModified).ToList();

        //get the history entry type from our calculated typeName
        var historyType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == historyTypeName);

        if(historyType != null)
        {

          //modified entries
          if (dbSet != null && historyDbSet != null && entry.State == EntityState.Modified)
          {
            var existingEntry = dbSet.Find(entry.Property("Id").CurrentValue);

            //create history record and add entry to table
            var newHistories = GetHistoricalEntities(existingEntry, type, entry);

            var listType = typeof(List<>).MakeGenericType(new[] { historyType });
            var typedHistories = (IList)Activator.CreateInstance(listType);

            //TODO: turn newHistories (type = List<HistoricalEntity>) into specific list type (List<MyObjectHistory>) so I can addrange on appropriate DbSet (MDbSet<MyObjectHistory>)

            historyDbSet.AddRange(newHistories);
          }
        }
Run Code Online (Sandbox Code Playgroud)

Cal*_*alC 1

您可以使用AutoMapper来映射您的历史实体。我刚刚创建了一个小测试,希望它能复制您的情况:

IList dogs = new List<Dog>() { new Dog { Id = 1, Name = "Alsatian" }, new Dog { Id = 2, Name = "Westie" } };
var dogHistoryType = typeof(DogHistory);
var listType = typeof(List<>).MakeGenericType(new[] { dogHistoryType });
var typedHistories = (IList)Activator.CreateInstance(listType);

mapper.Map(dogs, typedHistories);

foreach (var historyItem in typedHistories)
{
    this.Add(historyItem);
}
Run Code Online (Sandbox Code Playgroud)