n 層の切断されたエンティティ クラスの個々の変更されたプロパティを追跡するために、カスタマイズされた方法を使用しています。から抽出しました
プログラミング エンティティ フレームワーク: Julia Lerman と Rowan Miller (O'Reilly) による DbContext。Copyright 2012 Julia Lerman and Rowan Miller, 978-1-449-31296-1.
コードは次のとおりです。
public void ApplyChanges<TEntity>(TEntity root) where TEntity : class, IObjectWithState {
// bind the entity back into the context
dbContext.Set<TEntity>().Add(root);
// throw exception if entity does not implement IObjectWithState
CheckForEntitiesWithoutStateInterface(dbContext);
foreach (var entry in dbContext.ChangeTracker.Entries<IObjectWithState>()) {
IObjectWithState stateInfo = entry.Entity;
if (stateInfo.State == RecordState.Modified) {
// revert the Modified state of the entity
entry.State = EntityState.Unchanged;
foreach (var property in stateInfo.ModifiedProperties) {
// mark only the desired fields as modified
entry.Property(property).IsModified = true;
}
} else {
entry.State = ConvertState(stateInfo.State);
}
}
dbContext.SaveChanges();
}
このメソッドの目的は、SaveChanges() の次の呼び出しで定義済みのエンティティ フィールドのセットのみを更新する準備ができていることを EF に知らせることです。これは、エンティティが ASP.NET MVC 3 で次のように機能することを回避するために必要です。
最初のページ読み込み時: コントローラーの Get アクションがエンティティ オブジェクトを読み込み、それをパラメーターとしてビューに渡します。
ビューは、エンティティの 2 つのフィールドを編集するためのコントロールを生成し、隠しフィールドにレコードの ID を保持します。
[保存] を押してエンティティをコントローラーに戻すと、ビューに保存されている 3 つのフィールドを除くすべてのフィールドに null 値が含まれます。これは、MVC バインディング マネージャーの既定の動作です。
変更をデータベースに保存すると、更新クエリはもちろん、マップされていないフィールドを次のような文で上書きします。
UPDATE non_mapped_field_1 = NULL, ..., mapped_field_1 = 'mapped_value_1', mapped_field_2 = 'mapped_value_2', ... non_mapped_field_n = NULL WHERE ID = mapped_field_3
これが、フィールドを個別に追跡し、関心のあるフィールドのみを更新しようとしている理由です。ApplyChanges() でカスタム メソッドを呼び出す前に、更新に含めたいフィールドのリストを追加しています。 IObjectWithState.ModifiedProperties リスト。次のように SQL ステートメントを取得します。
UPDATE mapped_field_1 = 'mapped_value_1', mapped_field_2 = 'mapped_value_2' WHERE id = mapped_value_3
問題は、フィールドの 1 つを ApplyChanges で変更済みとしてマークする場合です。つまり、次のようになります。
entry.Property(property).IsModified = true;
システムは次の例外をスローしています:
{System.InvalidOperationException: Member 'IsModified' cannot be called for property 'NotifyCEDeadline' on entity of type 'User' because the property is not part of the Entity Data Model.
at System.Data.Entity.Internal.InternalPropertyEntry.ValidateNotDetachedAndInModel(String method)
at System.Data.Entity.Internal.InternalPropertyEntry.set_IsModified(Boolean value)
at System.Data.Entity.Infrastructure.DbPropertyEntry.set_IsModified(Boolean value)
...
そこで質問です。この EF 検証をバイパスする方法、または変更しようとしているこのシステム プロパティ (IsModified) の存在をコンテキストに知らせる方法はありますか?
アーキテクチャの概要:
- 最初に EF コード (注釈 + Fluent API)
- Oracle .NET EF データ プロバイダー (ODAC)
コンテキストは、nInject.MVC を使用してカスタム ビジネス コンテキストに注入されます => これが、ApplyChanges() メソッドをカスタマイズした理由です。
using (var context = new BreakAwayContext()){ context.Set().Add(root);
すでに初期化されている dbcontext への単純な呼び出し
dbContext.Set().Add(ルート);
Oracle データベースは、EF の助けを借りずに手動で作成されるため、EF メタデータ テーブルは使用されません。
ありがとう、イワン。