2016-10-28 18 views
3

IDbCommandInterceptorインターフェイスの説明はあまりよくありません。そして、私はそれにいくつかの希少なチュートリアルを見つけた:EntityFrameworkへのIDbInterceptorを1回だけDbContextにフックする

とSOいくつかの質問を:


これらは私が見つけたフックの提案です:

を - 静的DbInterceptionクラス:

DbInterception.Add(new MyCommandInterceptor()); 

- configファイルの使用 - DbConfigurationクラス

public class MyDBConfiguration : DbConfiguration { 
    public MyDBConfiguration() { 
     DbInterception.Add(new MyCommandInterceptor()); 
    } 
} 

に上記の提案をしている:私はフックする方法を見つけ出すことができませんでしたが、

<entityFramework> 
    <interceptors> 
    <interceptor type="EFInterceptDemo.MyCommandInterceptor, EFInterceptDemo"/> 
    </interceptors> 
</entityFramework> 

DbConfigurationクラスをDbContextに割り当て、configメソッドのtype部分には何も入れません。

type="System.Data.Entity.Infrastructure.Interception.DatabaseLogger, EntityFramework" 

私はDataBaseLoggerIDisposableIDbConfigurationInterceptorIDbInterceptor
を実装して次のように述べている。Another example I foundあなたはロガーの名前空間を作成することを示唆しているように見えました。 IDbCommandInterceptorIDbInterceptorを実装していたので、私はこのようにそれをフォーマットする(成功せず)みました:

type="DataLayer.Logging.MyCommandInterceptor, DataLayer" 

そして、私が直接静的DbInterceptionクラスを呼び出したときに、それは別の迎撃にすべての呼び出しを追加しました。だから私のすばやく解決策は、静的なコンストラクタを利用することでした:

//This partial class is a seperate file from the Entity Framework auto-generated class, 
//to allow dynamic connection strings 
public partial class MyDbContext // : DbContext 
{ 
    public Guid RequestGUID { get; private set; } 

    public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString) 
    { 
     DbContextListeningInitializer.EnsureListenersAdded(); 

     RequestGUID = Guid.NewGuid(); 
     //Database.Log = m => System.Diagnostics.Debug.Write(m); 
    } 

    private static class DbContextListeningInitializer 
    { 
     static DbContextListeningInitializer() //Threadsafe 
     { 
      DbInterception.Add(new MyCommandInterceptor()); 
     } 
     //When this method is called, the static ctor is called the first time only 
     internal static void EnsureListenersAdded() { } 
    } 
} 

しかし、それを行うにはどうすればよいですか?

[DbConfigurationType(typeof(MyDBConfiguration))] 
public partial class MyDbContext // : DbContext 
{ 
    public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString) 
    { } 
} 

public class MyDBConfiguration : DbConfiguration { 
    public MyDBConfiguration() { 
     this.AddInterceptor(new MyCommandInterceptor()); 
    } 
} 

答えて

5

は、私は私のDbContextクラスはちょうど、DbConfigurationType属性を持つように、実行時に設定を取り付けるために必要なことを考え出し

protected void Application_Start() 
{ 
    AreaRegistration.RegisterAllAreas(); 
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
    RouteConfig.RegisterRoutes(RouteTable.Routes); 
    BundleConfig.RegisterBundles(BundleTable.Bundles); 
    DbInterception.Add(new SchoolInterceptorTransientErrors()); 
    DbInterception.Add(new SchoolInterceptorLogging()); 
} 

重要な部分は、一度だけ呼び出されることです。

+0

これはスレッドセーフではないと思います。別のスレッドにMyDBConfiguration2と同様のコンストラクタ本体があるとどうなりますか?次に、両方のDbContextのMyCommandInterceptorが2回登録されます。 –

+1

あなたの 'MyDBConfiguration'コンストラクタで、あなたは' this.AddInterceptor() 'メソッドを持っている静的クラスを使う必要はありません。 –

+0

@JohnZabroski DbInterception.Add()がスレッドセーフではないことを意味しますか? [ドキュメント](https://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.interception.dbinterception.add(v = 1173).aspx)ではそうは言いませんが、私はあなたが正しいと思います。 Jan'splite'K。の提案は論理的な答えのように見えます。そして、それが動作することを確認するためにテストしました。それに応じて答えを更新。 –

0

docsはあなただけApplication_Startにそれを置くことができることを示唆している:

関連する問題