在SaveChanges上使用ObjectContext进行实体框架审计

时间:2014-10-30 22:43:08

标签: c# database entity-framework

对于审计日志记录,我需要获取所有列的值,包括已为数据库中的某个表修改的FK实体和关系实体。数据库基本上是一个用户可以上传资源(文件,在线文档,图片等)的网站,我有一个名为Material的表,它有多个2-many-n-one-2-one关系,如{ {1}},Material - Audience,'Material-Uploader','Material-Permission Material - Category等。我想记录发生在Material -Tags的所有更改。例如,如果有人从材料中删除了标签,那么我需要记录:

  • [User12 - 12/12/12] - 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本身的名称。我尝试过将CategoryDBDataRecord投射到CurrentValueRecord,但它只是EntityKey。有没有办法使用NULL解析这些FKsEntities

我的完整参考代码:

私有类SingleMaterialLogger {             MaterialAuditData auditData = new MaterialAuditData();             public void HandleEntity(ObjectStateEntry e,ObjectContext context){                 HandlePrimaryTypeChanges(E);                 HandleComplexTypeChanges(e,context);             }

ObjectStateManager

1 个答案:

答案 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模型上的名称/描述,那么这似乎会修改旧的审核日志。