对于审计日志记录,我需要获取所有列的值,包括已为数据库中的某个表修改的FK实体和关系实体。数据库基本上是一个用户可以上传资源(文件,在线文档,图片等)的网站,我有一个名为Material
的表,它有多个2-many-n-one-2-one关系,如{ {1}},Material - Audience
,'Material-Uploader','Material-Permission Material - Category
等。我想记录发生在Material -Tags
的所有更改。例如,如果有人从材料中删除了标签,那么我需要记录:
Material
标记已从Happy
资料中删除。到目前为止,我得到了这个:我可以使用以下内容获取所有已修改,添加,删除的Crappy
:
ObjectStateEntries
现在,我可以使用以下方法检查此context.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified)
是否为RelationShip:
ObjectStateEntry
在if (e.IsRelationship) {
HandleRelationshipEntry(e);
}
else {
HandleEntry(e);
}
方法中(条目不是关系条目),我可以检查HandleEntry
的类型,在我的情况下它是Entry
,所以我正在做:
Material
一次,我知道// We care about only Material which are modifed
if (e.State != EntityState.Modified || !(e.Entity is Material))
return;
的类型为Entry
,我可以使用以下内容获取Material Entry
表所有已更改的列:
Material
此时,我可以记录e.CurrentValues[ARCHIVE_COLUMN].ToString() != e.OriginalValues[ARCHIVE_COLUMN].ToString()
表的所有非FK更改。但是,如果列Material
与其他FK
列匹配,则无法将entity
值解析为对应的FK
。我可以知道Entity
已从CategoryID
更改为42
但我无法解析76
本身的名称。我尝试过将Category
和DBDataRecord
投射到CurrentValueRecord
,但它只是EntityKey
。有没有办法使用NULL
解析这些FKs
到Entities
?
我的完整参考代码:
私有类SingleMaterialLogger { MaterialAuditData auditData = new MaterialAuditData(); public void HandleEntity(ObjectStateEntry e,ObjectContext context){ HandlePrimaryTypeChanges(E); HandleComplexTypeChanges(e,context); }
ObjectStateManager
答案 0 :(得分:0)
我遇到了同样的问题。
使用id值提取任何实体类型并不困难:
DbContext.Set(entityType).Find(id)
但是,假设您首先从相关的导航属性中识别出实体类型。这需要一些智能,基本上通过使用反射来查看属性名称和[ForeignKey()]属性等来复制EF逻辑。
有些选择是:
1)添加智能以从FK ID属性中计算出FK模型属性。然后在审计日志创建过程中动态查找FK模型,并将.ToString()值存储在审计日志中。
这假定:
您的DataContext / Repository中有一个通用实用程序可以动态查找任何模型类型(例如DbContext.Set(entityType).Find(id))
您确信所有FK模型上的.ToString()实现都可以正常工作,原因如下:
他们从不依赖可能导致运行时错误的其他导航属性
您可以放心,您的模型查找中的其他导航属性已正确包含()
你启用了延迟加载(我强烈建议不要......但是......这会有所帮助)
您已经考虑过交易影响(如果您使用的是超出EF的交易)
2)在审核日志中存储FK ID。然后,在查看审核日志时,动态查找FK模型并在屏幕上呈现ToString()。
我们在项目中使用了此选项,它运行正常。
但是,您的审核要求可能更严格。例如,如果有人更改了FK模型上的名称/描述,那么这似乎会修改旧的审核日志。