从 IDbCommandInterceptor 的实现中获取 DbContext



我正在使用IDbCommandInterceptor实现:

public class MyInterceptor : IDbCommandInterceptor
{
    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        var context = interceptionContext.DbContexts.FirstOrDefault();
    }
    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
    }
    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
    }
    public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
    }
    public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
    }
    public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
    }
}

由此注入:

public class TestContext : System.Data.Entity.DbContext
{
    // …
    public TestContext()
        : base("TestConnectionString")
    {
        Database.SetInitializer<TestContext>(null);
        DbInterception.Add(new MyInterceptor());
    }
}

(也在静态构造函数中尝试过)。

interceptionContext.DbContexts总是空的。如何获取执行上下文的实例?可能吗?

这并不能完全回答我的问题,但我在实体框架文档中找到的解释是最准确的:

值得注意的是,拦截上下文是提供上下文信息的最佳努力。但是,在某些极端情况下,您期望的某些信息可能不存在。这是因为 EF 具有不容易更改的代码路径,并且不包含可能预期的信息。例如,当 EF 调用提供程序时,提供程序不知道正在使用的 DbContext。如果该提供程序(EF 外部)决定调用 ExecuteNonQuery,则可能会发生两种情况:

  • 首先,提供程序可能只是直接进行调用,完全避免 EF 拦截。(这是在 EF 级别而不是在堆栈中较低级别进行拦截的结果。如果拦截在堆栈中较低,那就太好了,但不幸的是,这超出了 EF 团队的控制范围。
  • 如果提供程序知道 EF 拦截,则它可以通过 EF 侦听器调度执行非查询调用。这意味着任何注册的拦截器都将收到通知并可以采取适当的行动。这就是 SQL Server 和 SQL Server Compact 提供程序所做的。但是,即使提供程序执行此操作,所使用的 DbContext 也可能不会包含在拦截上下文中,因为提供程序对此一无所知,并且允许这样做的更改将破坏明确定义的提供程序 API。

幸运的是,这种情况很少见,对于大多数应用程序来说可能不是问题。

我不知道我的情况如何"罕见",但也许我做错了什么......

最新更新