2016-11-30 19 views
14

既存のSQL Serverデータベースから生成されたEntity Framework 6コードファーストモデルがあります。データベースはSQL Server Change Trackingを使用しているため、EFから生成されるすべてのデータ操作操作に対して、Change Trackingコンテキストを設定して、他の外部プロセスによる変更と区別したいと考えています。これは通常、私は考えることができる唯一のことは、EFによって生成されたSQLに上記のSQL句を付加することである
WITH CHANGE_TRACKING_CONTEXT (@source_id) UPDATE <table>...Entity Framework 6でのSQL Server変更追跡のサポート

としてT-SQLで行われます。それが現れても、ORMによって生成されたSQLを変更したいのは疑問です。それでも、私がしたいと思っても、どこでそれができるのか分かりません。 EFコマンド傍受が目的に役立つことはありますか?

質問は、具体的にはEFの変更追跡ではなく、SQL Serverの変更追跡機能の使用に関するものです。 EFの面では、問題は、EF

+0

あなたの質問が正しいかどうかわかりません - 私が推測したものから、EF経由で更新が行われるたびにchnage_trackingを実行したいと思います。あなたはあなたの更新/追加/削除のために必要な追跡を持っているprocsを保存して、それをEFエンティティにマップすることができます。詳細はこちら - http://www.entityframeworktutorial.net/entityframework6/code-first-insert-update-delete-stored-procedure-mapping.aspx – Developer

答えて

0

[OPの明確化後の編集]

私はそれがEFクエリと混乱set up Change Tracking on the server sideに簡単に、ないと思うによって生成された修正SQLは約プログラムです。変更はすぐに入れトラッキング:

長所:

  • 軽量
  • セットアップは、トランザクションの一部(トランザクションが失敗した場合にロールバック)
  • まだ同期
  • のための非常に簡単
  • サポートです
  • SQLエージェントの依存関係がありません
  • 変更が完了しましたサイド通常のORMの変更操作(あなたのコードによって呼び出されるストアドプロシージャ、すべての変更は、アプリケーションの外部から発信)

短所:

  • ないより多くの情報を必要とし、監査のために合う
  • 少し遅く(CDC非同期性とは対照的に)同期して実行されたため(CDC非同期性とは対照的に)

[元の回答]

「通常の」変更に沿って変更/追跡情報を追加し、それらのすべてを単一のトランザクション内で有効にすることもできます。

DbContextSaveChangesメソッドをオーバーライドして、トラッキング情報のコードを追加できます。 ChangeTrackerリファレンスを使用すると、特定の状態(追加、更新、削除、変更なし)を持つすべてのエンティティを検索できるため、実行された変更の種類も保存できます。完全な実例はhereです。TrackerEnabledDbContext

このアプローチの利点は、いくつかの情報が監査されないように、あなたは簡単に、あなたのエンティティタイプをマークしていることである(いずれかのインターフェイスを実装するか -

A Nugetパッケージはaudingであなたを助けるためにそこにあると思われますカスタム属性を使用してください)。

プロパティのトラッキング属性を明示的に指定することで、変更の追跡をさらに細かく調整できるという利点もあります。

トランザクションが長くなり、一部のテーブルをロックする時間が長くなり、パフォーマンス上の問題が発生する可能性があります(これは時間あたりのトランザクション数に大きく依存します)。

また、このソリューションはコンテキストコード(EF)からの変更のみを捕捉し、データベースまたはストアドプロシージャ(外部プロセスまたはEFから呼び出されたという事実にかかわらず)に対して直接実行される変更は検出しません。 。

もう1つの方法は、サーバー側(SQL)Change Data Captureを使用して、この機能が有効になっているテーブルで行われたすべての変更をキャッチすることです。 CDCの重要な側面の1つは、監査対象のテーブル構造が変更されたときの動作です。詳細はthis articleをご覧ください。それは非同期で行われるため

  • が速くなる
  • より信頼性、データの変更は、さまざまなソース(手動で、ETL、ストアドプロシージャなど)から来る場合:

    サーバ側のアプローチは、2つの主要な利点を有します。

+0

質問は特にSQL Serverの変更の追跡についてですが、わかりやすくするために質問を更新してみましょう –

+0

変更の追跡は既に使用されていますが、もっと明確にすることはできないと思います... –

5

残念ながら、Entity Framework 6にはSQL Server変更追跡の組み込みサポートがありません。ただし、実行前に生成するSQLを変更できる傍受機能が公開されています。 ORMによって生成されるSQLを変更する際には、慎重に行う必要があり、正当な理由がある場合にのみ適切な解決策であるケースがあります。

EF6はIDbCommandInterceptorタイプを公開しており、クエリパイプライン全体にフックを与えます。このインタフェースを実装し、インターセプタをEFに登録するだけで簡単に必要です。

フレームワークでは、INSERT,UPDATE、およびDELETEの前にNonQueryExecutingが呼び出され、変更の追跡を行うのに最適です。簡単な例として

、このインターセプタを考慮する:EFは、DBの状態を変化させる任意のクエリを生成するとき

public class ChangeTrackingInterceptor : IDbCommandInterceptor 
{ 
    private byte[] GetChangeTrackingContext() 
    { 
     // TODO: Return the appropriate change tracking context data 
     return new byte[] { 0, 1, 2, 3 }; 
    } 

    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) 
    { 
     command.CommandText = "WITH CHANGE_TRACKING_CONTEXT (@change_tracking_context)\r\n" + command.CommandText; 

     // Create the varbinary(128) parameter 
     var parameter = command.CreateParameter(); 
     parameter.DbType = DbType.Binary; 
     parameter.Size = 128; 
     parameter.ParameterName = "@change_tracking_context"; 
     parameter.Value = GetChangeTrackingContext(); 
     command.Parameters.Add(parameter); 
    } 

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

    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) 
    { 
    } 

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

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

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

、クエリを実行する前にこのメソッドを呼び出します。これにより、標準SQLを使用してカスタムの変更追跡コンテキストを挿入する機会が与えられます。 EFであなたのインターセプタを登録するには

は、単にあなたの起動コードでDbInterception.Addどこかで呼び出す:

var changeTrackingInterceptor = new ChangeTrackingInterceptor(); 
DbInterception.Add(changeTrackingInterceptor); 

IDbCommandInterceptorインターフェースに大きなドキュメントのトンはありませんが、this MSDN articleは、開始するには良い場所です。

+0

これは私はそれを働かせようとしていた方法ですが、それを行うことができませんでした。 Infactはインターセプタをまったく動かすことができず、その後、健康状態が悪いために仕事を離れる必要がありました。私が仕事に戻るとすぐにもう一度お試しになりますので、ここまでフィードバックを残してください。今まで私の側からはテストされていません –

関連する問題