c# - 在 Entity Framework 中实现 "generic"机制来处理时态数据

标签 c# entity-framework temporal

我正在尝试使用 Entity Framework 实现一种“通用”机制来更新我的 SQL Server 数据库中的时态数据。

我所做的是创建一个名为 ITemporalData 的“标记”接口(interface),它定义了两个需要存在的属性 - DateTime ValidFromDateTime?有效期至

public interface ITemporalData
{
    DateTime ValidFrom { get; set; }
    DateTime? ValidTo { get; set; }
}

我希望在我的 DbContext.SaveChanges() 重写中实现一种“通用”方法:

  • 克隆任何 ITemporalData 对象,这会给我一个要存储的新对象 (EntityState.Added),并将其 ValidFrom 值设置为当前日期和时间
  • 将修改后的原始条目重置为其数据库值(在实体上调用 .Reset()),然后将“旧”记录的 ValidTo 设置为当前日期和时间

虽然我可以像这样在 SaveChanges() 重写中轻松过滤掉修改过的 ITemporalData 对象:

public partial class MyDbContext
{
    // override the "SaveChanges" method
    public override int SaveChanges()
    {
        DateTime currentDateTime = DateTime.Now;

        // get the modified entities that implement the ITemporalData interface
        IEnumerable<DbEntityEntry<ITemporalData>> temporalEntities = ChangeTracker.Entries<ITemporalData>().Where(e => e.State == EntityState.Modified);

        foreach (var temporalEntity in temporalEntities)
        {
            // how would I do that, really? I only have an interface - can't clone an interface...... 
            var cloned = temporalEntity.Entity.Clone();

            // and once it's cloned, I would need to add the new record to the correct DbSet<T> to store it

            // set the "old" records "ValidTo" property to the current date&time
            temporalEntity.Entity.ValidTo = currentDateTime;
        }

        return base.SaveChanges();
    }
}

我正在努力使用“克隆修改后的记录”方法 - 我只有一个 ITemporalData 接口(interface),真的 - 但克隆(使用 AutoMapper 或其他方法)总是取决于 实际,底层具体数据类型......

最佳答案

要克隆实体,您可以通过反射创建新实例 (Activator.CreateInstance) 并通过反射将所有原始(非导航)属性复制到它。最好不要为此使用自动映射器工具,因为它们也会访问导航属性,这可能会导致延迟加载(或至少确保禁用延迟加载)。

如果你不喜欢反射(注意自动映射器无论如何都会使用它)——你也可以从ICloneable继承你的接口(interface)并为每个实现Clone方法ITemporalData 实体(如果您的实体是自动生成的 - 为此使用分部类)。然后每个实体自己决定如何克隆,而不进行任何反射(reflection)。如果您的克隆逻辑很复杂(例如涉及从导航属性克隆相关对象),这种方式也有好处。

要添加实体以更正 DbSet,请使用未类型化 Set DbContext 的方法:

this.Set(temporalEntity.GetType()).Add(temporalEntity);

关于c# - 在 Entity Framework 中实现 "generic"机制来处理时态数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37552951/

相关文章:

c# - IIS 在异步请求的每个响应之间延迟很多

c# - WIQL : How to get the content of a field of a work item returned by a query

SQL Azure 联合和原子单元标识

sql-server - 更改系统版本控制表(临时表)列的最佳机制?

spatial - 用于空间和时间推理的规则引擎?

ruby-on-rails - 在 Rails 中实现租赁商店 : how to track an inventory state over time?

c# - 仅在 C# 中的特定时间触发事件

c# - LINQ to Entities 无法识别方法 NotSupportedException

sql-server - 如何将 MS SQL 数据类型 numeric(19, 0) 映射到 .NET 类型

c# - 方法 ‘Skip’ 仅支持 LINQ to Entities 中的排序输入。必须在方法 ‘OrderBy’ 之前调用方法 ‘Skip’