Entity Framework を使用したスナップショット履歴
-
12-09-2019 - |
質問
Entity Framework を使用した監査フックをいくつか検討してきました。それらの多くは、新旧の値の比較を示しています。これは監査証跡には最適ですが、私はオブジェクトのスナップショットを探しています。
例えば...製品を管理するアプリケーションがあるとします。製品には複数の属性と、関連する他のオブジェクトがあります。オブジェクトを 10 回変更したとします。また、これらのオブジェクト変更の画面 (監査証跡ではなく、読み取り専用形式で実際に画面がどのように見えたか) を表示できることが重要であるとも言えます。私が興味があるのは、これらの 10 個の変更すべて (見たいものに応じて) の元の EF 製品オブジェクト (関連するすべてのデータを含む) を取得し、それを使用して画面にバインドできることです。
SQL Server を使用している場合、現在シリアル化されたオブジェクトにはどの型 (XML、BLOB など) を使用する必要がありますか?これを行うことに意味はありますか?
解決
を見てみましょう。あなたは、オブジェクトグラフを取り、あなたが後でそれを具現化することができます形式のデータベースにそれをシリアル化する必要があります。私は正確にこれを行うツールがあると思います。そのうちの一つは、それが私を打つ、Entity Frameworkのです。
何がやりたいことは非常に一般的なものです。 Wikiエンジンを考えてみましょう。 Wikiは、誰もが見ることをチップリビジョンを持っている必要があり、加えて、すべての文書の背面改訂。 Wikiはまたチップリビジョンが表示されていることをちょうど同じように戻ってリビジョンを表示できるようにする必要があります。したがって、同一の記憶フォーマットは、それらの両方のために使用されるべきである。
私はあなたのエンティティタイプのすべてのバージョン管理を可能にすることを提案します。あなたはエンティティタイプを編集するときは、チップリビジョンを編集し、前の値を含むバックリビジョンを格納します。 (代わりに新しいチップを挿入するあなたはチップリビジョンを編集する理由は、他のオブジェクトは、現在のObjectContextにマテリアライズされていないので、むしろへのリンクより、あなたは先端へのリンクとして保存したい先端へのリンクが含まれていることですバック改正。)
必要に応じてバックリビジョンは、異なるファイルグループに格納されるように、あなたはあなたのSQL Serverテーブルを分割することができます。これは、個別にバックアップするチップリビジョンとバックのリビジョンをあなたにできるようになります。
他のヒント
まず、一連のプロパティをテーブルに追加する必要があります。
- バージョン - 最終変更時刻 (時刻の代わりに自動インクリメントするカウンターにすることもできます)。
- LastModifiedBy - 最後に変更を行ったユーザーへの参照 (保存している場合)。
次に、バージョン履歴を保存する方法についていくつかのオプションがあります。あなたはできる
履歴を保存したいメインテーブルごとに新しいテーブルを作成します。履歴テーブルにはメイン テーブルと同じフィールドがすべて含まれますが、主キーと外部キーは強制されません。各外部キーについては、バージョン作成時の参照エントリのバージョンも保存します。
または、エンティティに関する興味深いすべてをシリアル化し、バージョン管理したいすべてのエンティティのシリアル化された BLOB をすべて 1 つのグローバル履歴テーブルに保存することもできます (個人的には最初のアプローチを好みます)。
履歴テーブルにどのように記入しますか?更新および削除トリガー経由。
- エンティティの更新トリガーで、以前のすべての値を履歴テーブルにコピーします。各外部キーについて、参照されるエンティティの現在のバージョンもコピーします。
- 削除トリガーでも、基本的には同じことを行います。
最近のシステムでは実際には何も削除しないものが増えていることに注意してください。彼らはただ マーク 削除されたもの。このパターン (これにはいくつかの利点があります) に従いたい場合は、削除する代わりに、IsDeleted フラグをエンティティに追加します (もちろん、その後、削除されたエンティティをあらゆる場所でフィルター処理する必要があります)。
自分の歴史をどのように見ていますか?メインテーブルと同じプロパティがすべてあるため、履歴テーブルを使用するだけで問題ありません。ただし、外部キーを展開する場合は、参照されるエンティティのバージョンが履歴テーブルに保存したものと同じであることを確認してください。そうでない場合は、その参照されたエンティティの履歴テーブルに移動し、そこで値を取得する必要があります。こうすることで、すべての参照を含め、その瞬間にエンティティがどのように見えたかのスナップショットを常に取得できます。
上記すべてに加えて、エンティティの状態を以前のバージョンに復元することもできます。
この実装は簡単ではありますが、スペースを消費する可能性があることに注意してください。 スナップショット, 変更が加えられるだけではありません。変更を保存するだけの場合は、更新トリガーでどのフィールドが変更されたかを検出し、それらをシリアル化し、グローバル履歴テーブルに保存できます。そうすることで、少なくともユーザー インターフェイスに何が変更されたのか、誰によって変更されたのかを示すことができます (ただし、以前のバージョンに戻すのに問題が発生する可能性があります)。
最近構築したプロジェクトでは、 SaveChanges
のメソッド DbContext
クラス。これにより、次のインスタンスにアクセスできるようになりました。 ChangeTracker
クラス。電話をかける ChangeTracker.Entries()
のリストにアクセスできます DbEntityEntry
. DbEntityEntry
には、次の興味深いプロパティとメソッドがあります。
State
- 新しく作成されたオブジェクト、変更されたオブジェクト、または削除されたオブジェクトですEntity
- オブジェクトのそのままのコピーCurrentValues
- 編集された値の列挙OriginalValues
- 元の値の列挙
変更セットと変更用の POCO のセットを作成し、EF を通じてアクセスできるようにしました。これにより、ユーザーはフィールド レベルの変更を日付および責任ユーザーとともに表示できるようになりました。