1

我会尽量在这篇文章中尽可能地描述。我已经阅读了十几个与我的问题外围相关的 SO 问题,但到目前为止,没有一个与正在发生的事情相匹配。

因此,为了对我们的数据库事务(创建、更新、删除)执行审计日志记录,我们的设计使用了 IAuditable 接口,如下所示:

public interface IAuditable
{
    Guid AuditTargetId { get; set; }

    int? ContextId1 { get; }
    int? ContextId2 { get; }
    int? ContextId3 { get; }
}

这三个上下文 ID 与域模型的布局方式有关,如前所述,它们中的一些或全部可能为空,具体取决于被审计的实体(它们用于过滤目的,以便管理员只想查看应用程序特定范围的审核日志)。任何需要对 CUD 操作进行审计的模型只需要实现这个接口。

审计表本身的填充方式是通过位于基本 DbContext 和我们域的上下文之间的 AuditableContext。它包含审计表 DbSets,并使用 EF ChangeTracker 覆盖 SaveChanges 方法,如下所示:

foreach (var entry in ChangeTracker.Entries<IAuditable>())
{
    if (entry.State != EntityState.Modified && 
        entry.State != EntityState.Added && 
        entry.State != EntityState.Deleted)
    {
        continue;
    }

    // Otherwise, make audit records!
}

base.SaveChanges();

“制作审计记录”过程是一段稍微复杂的代码,它使用反射和其他有趣的东西来提取需要审计的字段(可审计模型有一些方法可以让它们的一些字段“退出”审计)以及所有这些。

所以这个逻辑很好。当我有这样的可审计模型时,问题就来了:

public class Foo: Model, IAuditable
{
    public int FooId { get; set; }

    // other fields, blah blah blah...

    public virtual Bar Bar { get; set; }

    #region IAuditable members

    // most of the auditable members are just pulling from the right fields

    public int? ContextId3
    {
        get { return Bar.BarId; }
    }

    #endregion
}

正如所指出的,在大多数情况下,这些上下文审计字段只是模型的标准属性。但是在某些情况下,例如这里,需要从虚拟复杂属性中提取上下文 id。

这最终导致NullReferenceException尝试从 SaveChanges() 方法中获取该属性时 - 它表示虚拟 Bar 属性不存在。我已经阅读了一些有关如何构建 ChangeTracker 以允许延迟加载复杂属性的信息,但我找不到正确的语法。“原始值”列表中不存在这些字段,并且对象状态管理器没有这些字段,我猜是因为它们来自接口而不是直接被审计的实体。

那么有谁知道如何解决这个奇怪的问题?我可以强制急切加载整个对象,包括虚拟属性,而不是显然很顽固的延迟加载吗?

很抱歉这篇冗长的帖子,我觉得这是一个非常具体的问题,可能需要详细信息。

蒂亚!:)

4

0 回答 0