从实现IDbCommandInterceptor的DbContext获取

4

我正在使用一个 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始终为空。我如何获取正在执行的上下文实例?这可能吗?
1个回答

4
这并不能完全回答我的问题,但我在Entity Framework文档中找到的解释是最准确的:
值得注意的是,拦截上下文是尽力提供上下文信息的。然而,在某些边角情况下,你期望出现的一些信息可能不存在。这是因为EF有些代码路径无法轻易更改,并且不包括可能被期望的信息。例如,当EF调用提供程序时,提供程序不知道正在使用的DbContext。如果该提供程序在EF之外决定调用ExecuteNonQuery,那么可能会发生两件事:
首先,提供程序可能直接进行调用,完全避免EF的拦截。(这是在EF级别而不是堆栈较低处进行拦截的结果。如果拦截位于堆栈较低处,那将是很好的,但不幸的是这超出了EF团队的控制范围。)
如果提供程序知道EF的拦截,则可以通过EF拦截器分派ExecuteNonQuery调用。这意味着任何已注册的拦截器都将得到通知,并可适当地采取行动。这就是SQL Server和SQL Server Compact提供程序所做的。但是,即使提供程序这样做,使用的DbContext也可能不会被包括在拦截上下文中,因为提供程序不知道它,并且更改以允许这样做将破坏定义良好的提供程序API。
幸运的是,这种情况很少见,对于大多数应用程序来说可能不是问题。
我不知道我的情况为什么是“罕见”的,但也许我做错了什么...

3
我也在尝试研究这个问题,我的结论是拦截是一个事后加入的一堆 hack。最大的问题是 DbInterception 是一个静态类,因此整个应用程序域中所有拦截都是全局的。你无法创建一个 IsolationLevelDbCommandInterceptor 仅为一个上下文更改孤立级别。同样,也没有办法确保一个上下文只被添加一次。 - John Zabroski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接