この投稿では、できる限り説明的になるように努めます。私の問題に周辺的に関連するSOの質問を1ダース以上読んだことがありますが、これまでのところ、何が起こっているのかと一致するものはありません.
したがって、データベース トランザクション (作成、更新、削除) で監査ログを実行するために、設計では次のように IAuditable インターフェイスを使用します。
public interface IAuditable
{
Guid AuditTargetId { get; set; }
int? ContextId1 { get; }
int? ContextId2 { get; }
int? ContextId3 { get; }
}
3 つのコンテキスト ID は、ドメイン モデルのレイアウト方法に関連しており、前述のように、監査対象のエンティティに応じて、それらの一部またはすべてが null になる場合があります (これらは、管理者がアプリケーションの特定の範囲の監査ログ)。CUD アクションで監査する必要があるモデルは、このインターフェースを実装するだけで済みます。
監査テーブル自体が設定される方法は、ベース DbContext とドメインのコンテキストの間にある AuditableContext を使用することです。これには監査テーブル DbSets が含まれており、次のように EF ChangeTracker を使用して SaveChanges メソッドをオーバーライドします。
foreach (var entry in ChangeTracker.Entries<IAuditable>())
{
if (entry.State != EntityState.Modified &&
entry.State != EntityState.Added &&
entry.State != EntityState.Deleted)
{
continue;
}
// Otherwise, make audit records!
}
base.SaveChanges();
「監査レコードを作成する」プロセスは、リフレクションやその他の楽しいことを使用して、監査が必要なフィールドを抽出する少し複雑なコードです (監査可能なモデルがフィールドの一部を監査から「オプトアウト」する方法があります)。そしてそのすべて。
したがって、そのロジックはすべてうまくいっています。問題は、次のような監査可能なモデルがある場合に発生します。
public class Foo: Model, IAuditable
{
public int FooId { get; set; }
// other fields, blah blah blah...
public virtual Bar Bar { get; set; }
#region IAuditable members
// most of the auditable members are just pulling from the right fields
public int? ContextId3
{
get { return Bar.BarId; }
}
#endregion
}
指摘されているように、ほとんどの場合、これらのコンテキスト監査フィールドはモデルの標準プロパティにすぎません。ただし、ここのように、仮想複合プロパティからコンテキスト ID を取得する必要がある場合もあります。
これによりNullReferenceException
、SaveChanges() メソッド内からそのプロパティを取得しようとすると、仮想 Bar プロパティが存在しないと表示されます。複雑なプロパティの遅延読み込みを可能にするために ChangeTracker がどのように構築されているかについて読んだことがありますが、それを正しく行うための構文が見つかりません。フィールドは「元の値」リストに存在せず、オブジェクト状態マネージャーにはこれらのフィールドがありません。これは、監査対象のエンティティではなくインターフェイスから取得されたためだと思います。
では、この奇妙な問題を回避する方法を知っている人はいますか? どうやら頑固な遅延読み込みの代わりに、仮想プロパティを含むオブジェクト全体の熱心な読み込みを強制することはできますか?
長い投稿で申し訳ありませんが、これは本当に具体的な問題であり、おそらく詳細が必要だと思います.
ティア!:)