我在实现我的计划时遇到了一些错误,如下所述。此时我对解决特定错误并不感兴趣,而是对这是否是一个好主意感兴趣。
所有支持历史记录的对象都源自具有单个属性的公共(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 的记录:
采用这种方法
可以跟踪任何实体(表)
报告将可读
仅记录更改。
关于c# - EF Code-First 继承单个基类以实现简单的历史性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20028547/