我遇到了一些实施我的计划的错误,如下所述。我对解决特定错误的兴趣并不是很感兴趣,因为我知道这是不是一个好主意。
所有具有历史记录的对象都来自具有单个属性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从单个类降序是否有明显的缺点?
答案 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中插入两条记录:
采用这种方法
可以跟踪任何实体(表格)
报告将是可读的。只记录更改。