すべてのプロパティがvirtual
Entity Framework の場合、デフォルトで POCO の動的プロキシが自動的に作成されます。私が間違っていなければ、変更の追跡は、この場合、この動的オブジェクトのプロパティ セッターに基づいています。
private string _name;
public string Name
{
// ...
set
{
// if (_name != value) such a check probably does not happen
{
_name = value;
MarkPropertyAsModified(...);
}
}
}
そのため、元の値との比較はなく、プロパティの現在の値とのみ比較されます。この値が変更されると、元の値にリセットしても、プロパティは変更済みとしてマークされます。
(前の段落の編集と修正:同じ値または変更された値が割り当てられているかどうかに関係なく、setter が呼び出された場合、プロパティは Modified としてマークされます。Brad Thomas と彼の以下のコメントに感謝します!)
コンテキスト オプションでこれを無効にすることで、動的プロキシの作成を避けることができます。
objectContext.ContextOptions.ProxyCreationEnabled = false;
変更検出は、スナップショットの作成に依存するようになりました。つまり、変更検出が呼び出されたときに、EF は元の値 (オブジェクト コンテキストのスナップショットに格納されている) と現在の値を比較します。これは、プロパティ セッターでは発生しなくなりましたが、Entity Framework の特定の関数内 ( SaveChanges
. あなたの状況では、SaveChanges
元の値 (スナップショット) を呼び出すと、変更をリセットしたため、現在の値が同じになることを意味します。基本的に、EF はプロパティを 2 回変更したことに気付かず、プロパティが変更されていないと見なします。
プロキシの作成を無効にすると (コンテキスト コンストラクターなどでグローバルに行う場合)、アプリケーションに深刻な影響を与える可能性があることに注意してください。正しく動作するために動的プロキシに依存するコードがあり、さまざまな状況でパフォーマンスに大きな影響を与える可能性があります。動的プロキシは、変更の追跡を高速化するために存在します。スナップショット ベースの変更追跡は、はるかに低速です。