Getting DbContext from implementation of IDbCommandInterceptor
Asked Answered
D

1

5

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?

Dirkdirks answered 11/3, 2015 at 19:26 Comment(0)
D
5

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…

Dirkdirks answered 16/3, 2015 at 8:27 Comment(1)
I am also trying to research this, and my conclusion is interception is a giant pile of hacks put in as an after-thought. The big problem is DbInterception is a static class, and therefore all interception is global across an AppDomain. You can't create a IsolationLevelDbCommandInterceptor that only changes Isolation level for one context. Likewise, there is no way to ensure a context is only added once.Mummery

© 2022 - 2024 — McMap. All rights reserved.