从实现IDbCommandInterceptor获取DbContext [英] Getting DbContext from implementation of IDbCommandInterceptor

查看:486
本文介绍了从实现IDbCommandInterceptor获取DbContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 IDbCommandInterceptor 实现:

  public class MyInterceptor:IDbCommandInterceptor 
{
public void ReaderExecuting(DbCommand命令,DbCommandInterceptionContext< DbDataReader> interceptionContext)
{
var context = interceptionContext.DbContexts.FirstOrDefault() ;
}

public void NonQueryExecuting(DbCommand命令,DbCommandInterceptionContext< int> interceptionContext)
{
}

public void ScalarExecuting(DbCommand命令,DbCommandInterceptionContext< object> interceptionContext)
{
}

public void NonQueryExecuted(DbCommand命令,DbCommandInterceptionContext< int> interceptionContext)
{
}

public void ReaderExecuted(DbCommand命令,DbCommandInterceptionContext< DbDataReader> interceptionContext)
{
}

public void ScalarExecuted(DbCommand命令,DbCommandInterceptionContext< object> interceptionContext)
{
}
}

注意:公共类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拦截器分派ExecuteNonQuery调用。这意味着任何已注册的拦截器都将被通知并可以适当地采取行动。这是SQL Server和SQL Server Compact提供商所做的。然而,即使提供者执行此操作,很可能正在使用的DbContext将不会包含在拦截上下文中,因为提供程序不知道它,并且允许这样做的更改会破坏定义良好的提供程序API。



幸运的是,这种情况很少见,大多数应用程序可能不会成为问题。


我不知道我的情况是如何罕见,但也许我在做错事...


I am using an IDbCommandInterceptor implementation:

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)
    {
    }
}

Injected by this:

public class TestContext : System.Data.Entity.DbContext
{
    // …

    public TestContext()
        : base("TestConnectionString")
    {
        Database.SetInitializer<TestContext>(null);
        DbInterception.Add(new MyInterceptor());
    }
}

(also tried in static constructor).

But interceptionContext.DbContexts is always empty. How can I get an instance of executing context? Is it possible?

解决方案

This does not fully answer my question but the explanation I found in Entity Framework documentation was the most accurate:

It’s worth noting that the interception context is a best effort to provide contextual information. However, in some corner cases some information that you would expect to be there may not be there. This is because EF has code paths that cannot easily be changed and do not include information that might be expected. For example, when EF makes a call into a provider, the provider has no knowledge of the DbContext being used. If that provider, outside of EF, decides to call ExecuteNonQuery, then two things might happen:

  • First the provider may just make the call directly, avoiding EF interception completely. (This is a consequence of having interception at the EF level rather than lower in the stack. It would be great if interception were lower in the stack, but this is unfortunately outside of the control of the EF team.)
  • If the provider is aware of EF interception then it can dispatch the ExecuteNonQuery call through EF interceptors. This means that any registered interceptor will be notified and can act appropriately. This is what the SQL Server and SQL Server Compact providers do. However, even when a provider does this it is likely that the DbContext being used will not be included in the interception context because the provider has no knowledge of it, and a change to allow this would break the well-defined provider APIs.

Luckily this kind of situation is rare and will likely not be an issue for most applications.

I don't know how my situation is "rare" but maybe I am doing something wrong…

这篇关于从实现IDbCommandInterceptor获取DbContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆