私は、さまざまなソースから個人情報を受け取るソフトウェアを作成しています。このデータはすべてデータベースに保存されます。注意が必要なのは、この情報がマスター レコードに結合されるときです。この結合は、ソースから受信した情報からマスター レコードを更新するさまざまな種類のステップのパイプラインとして実装されます。IPersonUpdatingStep
すべてのステップは、メソッドを持つ共通のインターフェースを実装しますUpdate(Person person)
。
どのフィールドが更新されたか、特にどのステップが変更の原因であったかを記録しておきたいと思います。さまざまなステップで同じフィールドが更新される可能性があり、マスター レコードがパイプライン全体を通過した後に存在する最後の変更のみに関心があります。
私の最初の本能は、オブジェクトがステップに入ったときにディープ コピーを取得し、戻った後に別のディープ コピーを取得し、これらのコピーに基づいて差分を作成することでした。ただし、Entity Framework の Database First ツールで生成されたクラスのオブジェクトをディープ コピーするのはかなり難しいようです。浅いコピーで十分であれば非常に簡単ですが、コレクションに保存されている関連エンティティが変更されたかどうかを知る必要があります。
ディープ コピーの簡単な解決策として、オブジェクトをシリアル化および逆シリアル化することを提案しましたが、モデルはデータベースに基づいて自動生成されるため、これらのシリアル化可能な属性を追加することはできません。
オブジェクトには関連エンティティと関連エンティティのコレクションがあるため、問題はさらに難しくなります。そのため、これらの関連コレクション エンティティの一部のプロパティが何らかのステップで変更されたかどうかを知る必要があります。
それぞれに次のようなコードが含まれるように、パイプラインのステップを変更したくありません。
if (targetPerson.FirstName != sourcePerson.FirstName)
{
targetPerson.FirstName = sourcePerson.FirstName;
changes.Add("FirstName", "Name of the step responsible for the change");
}
しかし、読みやすく信頼できる別のオプションはありますか? オブジェクトをデータベースに保存するときに、Entity Framework を使用して監査証跡を書き込む方法は認識していますが、その段階では、どのプロパティが変更されたかしかログに記録できません。分野。
私は、他の人が同じ問題に遭遇しないような画期的なことをしていないように感じます.
更新: ChangeTracker API に関する haim770 の提案は良いものでした。変更された基本プロパティに関する情報を取得できましたが、変更された関係に関する情報を取得するにはどうすればよいですか? たとえば、私のPerson
オブジェクトはオブジェクトと 1 対多の関係にありAddress
ます。Address
どのオブジェクトが更新されたかだけでなく、より具体的には、そのオブジェクトのどのプロパティが変更されたかについての情報を取得したいと考えていAddress
ます。
DbEntityEntry entry = _source.Context.Entry(person);
foreach (var property in entry.Entity.GetType().GetProperties())
{
DbMemberEntry propertyEntry = entry.Member(property.Name);
if (propertyEntry is DbPropertyEntry)
{
var foo = propertyEntry as DbPropertyEntry;
if (foo.IsModified)
{
changes.Add(step.GetType().Name + ": " + property.Name);
}
}
// How to handle relationships?
}