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

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

所有具有历史记录的对象都来自具有单个属性public Guid ID { get; set; } public Guid ID { get; set; } 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从单个类下载是否有任何明显的缺点?

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

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

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

如果我要去设计审计过程,我会使用Entity-attribute-value模型
使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 :(String)我们将审核不同的实体,该字段将用于获取有意义的报告。(必填)
2. ObjectIdentifier :正在被操纵的实体标识符,实体的主键或业务键。
3. FieldName :(字符串)实体字段名称。
4. OldValue :(字符串)实体字段旧值。
5. NewValue :(字符串)实体字段新值。
6. TransactionUser :进行更改的应用程序用户。 (强制)
7. TransactionID :任何更改实体的操作都需要具有唯一的事务ID(如GUID)(强制),如果实体更新多个字段,这些列将是跟踪所有更改的关键点。更新(transcation)
8. ChangeDate :交易日期。 (强制)
9. FieldType :显示字段类型(如TEXT或Double)的枚举或文本。 (强制)

在服务层中,当Taco1将要更新(或插入)时,我们将检查Taco1类型是否由IAuditableEntity使用reflection标记(使用惰性chash存储reflection数据),如果是,则更改了哪些属性(我们需要一个单独的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中插入两条记录:

在此处输入图像描述

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