EF 4.0 では、ObjectStateManager
を利用してこれを実現する完璧な方法があり
ます。まず、ObjectContext の部分クラスを作成し、
ObjectContext.SavingChanges Eventをサブスクライブする必要があります。このイベントをサブスクライブする最適な場所は、OnContextCreated メソッド内です。このメソッドは、コンテキスト オブジェクトのコンストラクターと、実装のない部分メソッドであるコンストラクター オーバーロードによって呼び出されます。
partial void OnContextCreated() {
this.SavingChanges += Context_SavingChanges;
}
ジョブを実行する実際のコードは次のとおりです。
void Context_SavingChanges(object sender, EventArgs e) {
IEnumerable<ObjectStateEntry> objectStateEntries =
from ose
in this.ObjectStateManager.GetObjectStateEntries(EntityState.Added
| EntityState.Modified)
where ose.Entity != null
select ose;
foreach (ObjectStateEntry entry in objectStateEntries) {
ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
.DataRecordInfo.FieldMetadata;
FieldMetadata modifiedField = fieldsMetaData
.Where(f => f.FieldType.Name == "LastModifiedUser").FirstOrDefault();
if (modifiedField.FieldType != null) {
string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;
if (fieldTypeName == PrimitiveTypeKind.String.ToString()) {
entry.CurrentValues.SetString(modifiedField.Ordinal, Lookupuser());
}
}
}
}
コードの説明:
このコードは、 LastModifiedUserプロパティを持つ追加または変更されたエントリを見つけ、そのプロパティをカスタムLookupuser()メソッドからの値で更新します。
foreach ブロックでは、クエリは基本的に各エントリのCurrentValuesにドリルダウンします。次に、Whereメソッドを使用して、そのエントリの各FieldMetaDataアイテムの名前を調べ、 NameがLastModifiedUserであるアイテムのみを選択します。次に、if ステートメントは、LastModifiedUserプロパティが文字列であることを確認します。
分野; 次に、フィールドの値を更新します。
このメソッドを接続する別の方法 ( SavingChangesイベントをサブスクライブする代わりに) は、 ObjectContext.SaveChanges Methodをオーバーライドすることです。
ところで、上記のコードは、プログラミング エンティティ フレームワークの本に掲載されているジュリー ラーマンのものです。
セルフ トラッキング POCO 実装の編集: セルフ トラッキング POCO
がある場合、最初に T4 テンプレートを変更して OnContextCreated() メソッドを呼び出すようにします。ObjectContext.tt ファイルを見ると、Initialize()があります。
すべてのコンストラクターによって呼び出されるメソッドであるため、OnContextCreated() メソッドを呼び出すのに適しているため、次のように ObjectContext.tt ファイルを変更するだけで済みます。
private void Initialize()
{
// Creating proxies requires the use of the ProxyDataContractResolver and
// may allow lazy loading which can expand the loaded graph during serialization.
ContextOptions.ProxyCreationEnabled = false;
ObjectMaterialized += new ObjectMaterializedEventHandler(HandleObjectMaterialized);
// We call our custom method here:
OnContextCreated();
}
これにより、コンテキストの作成時に OnContextCreated() が呼び出されます。
ここで、POCO をサービス境界の背後に配置すると、ModifiedUserNameには WCF サービス コンシューマーからの残りのデータが含まれている必要があることを意味します。この
LastModifiedUserプロパティを公開して更新するか、別のプロパティに格納されていてそのプロパティからLastModifiedUserを更新する場合は、次のように 2 番目のコードを変更できます。
foreach (ObjectStateEntry entry in objectStateEntries) {
ReadOnlyCollection fieldsMetaData = entry.CurrentValues
.DataRecordInfo.FieldMetadata;
FieldMetadata sourceField = fieldsMetaData
.Where(f => f.FieldType.Name == "YourPropertyName").FirstOrDefault();
FieldMetadata modifiedField = fieldsMetaData
.Where(f => f.FieldType.Name == "LastModifiedUser").FirstOrDefault();
if (modifiedField.FieldType != null) {
string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;
if (fieldTypeName == PrimitiveTypeKind.String.ToString()) {
entry.CurrentValues.SetString(modifiedField.Ordinal,
entry.CurrentValues[sourceField.Ordinal].ToString());
}
}
}
お役に立てれば。