EF Code-First继承了一个基类来实现简单的历史记录

时间:2013-11-17 07:59:19

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

我遇到了一些实施我的计划的错误,如下所述。我对解决特定错误的兴趣并不是很感兴趣,因为我知道这是不是一个好主意。

所有具有历史记录的对象都来自具有单个属性AuditableObject的公共类public Guid ID { get; set; }

后代可能是:

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

现在,我想实现save事件处理程序来写入下表(类)

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从单个类降序是否有明显的缺点?

1 个答案:

答案 0 :(得分:2)

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

或者序列化对象会导致问题。
假设我们要使用approch来审计Taco类的TacoOject1,序列化的数据将被放入数据库中,之后由于业务变化我们需要向Taco添加另一个属性,重新编译后我们需要deserilazed TacoOject1我们将获得TypeMissMatchException(不确定异常名称)。

另一个设计异议是将继承用于审计过程 第一个:实际上Taco is not a AuditableObject,它是由Taco玩的,使用继承将违反Liskov Substitution Principle
第二:你不能使用多重继承,认为如果我们有一个TacoSupperClass,我们如何审核Taco呢?

如果我要设计审核流程,我会使用Entity–attribute–value model使AuditItem成为标记界面并将其重命名为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存储反射数据),如果是,则更改了哪些属性(我们需要)一个单独的DB调用来获取旧值。) 例如:

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";

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

enter image description here

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