c# - EF Code-First 继承单个基类以实现简单的历史性

标签 c# entity-framework inheritance database-design ef-code-first

我在实现我的计划时遇到了一些错误,如下所述。此时我对解决特定错误并不感兴趣,而是对这是否是一个好主意感兴趣。

所有支持历史记录的对象都源自具有单个属性的公共(public)类 AuditableObject public Guid ID { get;放; }.

后代可能是:

public class Taco : AuditableObject { public string Seasoning { get;放; } }

现在,我想实现保存事件处理程序以写入下表(类)

public class AuditItem
{
    public Guid ID { get; set; }
    public virtual AuditableObject Object { get; set; }
    public string ObjectClassName { get; set; } //ugly
    public string OldObjectXMLData { get; set; }
    public string NewObjectXMLData { get; set; }
    public DateTime Timestamp { get; set; }
}

我不确定是否需要 ObjectClassName,因为我可以在运行时检查对象的类型,但它只是以防万一。

在保存时,我基本上会将对象之前和之后序列化到各自的属性,保存时间戳,并设置对象 - 即映射 FK。

这是一种丑陋的做法吗?像我一样使用 EF Code First 从单个类继承有任何明显的缺点吗?

最佳答案

我认为在脱盐时您将需要对象类型的完整限定名称,因此这是强制性的。

序列化对象也会给你带来问题。
假设我们要使用该方法审计Taco类的TacoOject1,序列化后的数据将放入数据库中,稍后由于业务变化需要向Taco添加另一个属性,重新编译后需要反序列化时TacoOject1 我们将得到 TypeMissMatchException (不确定异常名称)。

另一个设计反对意见是在审核过程中使用继承。
第一:实际上 Taco 不是 AuditableObject ,它是 Taco 玩的一个角色,使用继承会违反 Liskov Substitution Principle
第二:不能使用多重继承,想想如果我们有一个TacoSupperClass,我们如何审计Taco呢?

如果我要设计审核流程,我会使用Entity–attribute–value model
AuditItem 制作为标记接口(interface),并将其重命名为 IAuditableEntity
拥有一个名为 AuditableProperty 的属性将增强我们的流程。
任何需要审计的实体都会被IAuditableEntity标记,任何需要参与审计的实体的属性都会被AuditableProperty属性标记。

public class Taco : IAuditableEntity 
{ 
  [AuditableProperty]
  public string Seasoning { get; set; } 

  [AuditableProperty]
  public string OtherProperty1 { get; set; } 

  public string OtherProperty2 { get; set; } 

}

AuditLog 表将包含以下列:
1. EntityFullTypeName:(字符串)我们将审核不同的实体,该字段将用于获取有意义的报告。(强制)
2. ObjectIdentifier:正在操作的实体标识符,实体的主键或业务键。
3. FieldName:(字符串)实体字段名称。
4. OldValue:(字符串)实体字段旧值。
5. NewValue:(字符串)实体字段新值。
6. TransactionUser:进行更改的应用程序用户。 (必填)
7. TransactionID:任何更改实体的操作都需要有一个唯一的事务ID(如GUID)(强制),如果实体更新更改多个字段,这些列将是关键指向跟踪更新(事务)中的所有更改
8. ChangeDate:交易日期。 (必填)
9. FieldType:显示字段类型的枚举或文本,如 TEXT 或 Double。 (必填)

在服务层,当Taco1要更新(或插入)时,我们将检查Taco1类型是否由IAuditableEntity使用反射标记(使用惰性chash来存储反射数据),如果是,则哪些属性已更改(我们需要单独的数据库调用来获取旧值)。
例如:

Taco1 = new Taco(); 
Taco1.Seasoning = "old Seasoning value";
Taco1.OtherProperty1 = "Old Other Property1 value";
Taco1.OtherProperty2 = "Old Other Property2 value";

之前保存过,现在更新:

Taco1.Seasoning = "New Seasoning value";
Taco1.OtherProperty1 = "New Other Property1 value";
Taco1.OtherProperty2 = "New Other Property2 value";

我们将在 AuditLog 中插入两条具有相同 TransactionID 的记录:

enter image description here

采用这种方法
可以跟踪任何实体(表)
报告将可读
仅记录更改。

关于c# - EF Code-First 继承单个基类以实现简单的历史性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20028547/

相关文章:

c# - ASP.Net MVC - 正确执行 MVVM

c# - 使用 asp.net 的 Entity Framework 示例

c++ - 按类型对 std::vector 进行排序

c# - 获取ninject的具体实例

c# - Enumerable.Select 的 lambda 表达式

c# - 在 c# 代码中删除监听器/禁用跟踪源的日志

c# - 显示组合框中外键约束的名称

entity-framework - EF Core 2.0 迁移 - 具有附加字段的多对多

c++ - 如何继承模板函数?

python - 在 Python 中是否可以声明必须重写该方法?