Entity Framework 7で外部キーを更新する

c# entity-framework entity-framework-core foreign-keys sql-server

質問

Entity Framework 7を使用して外部キーを更新しようとしています。ただし、エラーが発生しています。オブジェクト 'X'にプロパティ 'Y'が見つかりませんでした。私はさまざまな解決策を試しましたが、まだうまくいきません。サンプルコード:

class X
{
  property Y {get; set;} -> property Y is a foreign key and also a complex type
}

テーブル 'X'には、外部キーであるカラム 'Y_ID'があります。

注:外部キーを更新したいだけです。例えば、 最初はクラス 'X'が 'NULL'を指していますがクラス 'X'を 'Y1'を指すように更新し ます。

Entity Framework 7のコード:

var x = this.GetX();
this.mainContext.Xs.Attach(x);
var xEntry = this.mainContext.Entry(x);

xEntry.Property("Y").CurrentValue = "Y1"; // Error at this line

await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

詳細なエラー:

エンティティタイプ 'X'のプロパティ 'Y'が見つかりませんでした。プロパティが存在し、モデルに含まれていることを確認してください。

編集する

Fabienが彼のコメントで提案したアプローチはうまく機能します。しかし、問題は、更新するプロパティが実行時にしかわからないということです。これを実現するためにリフレクションを使用する場合、問題はエンティティフレームワークがオブジェクトを新しいものとして扱い、作成しようとし(INSERT)、主キー違反をスローすることです(重複エントリは許可されていません)。

それで、EFの外部キーのように振る舞うオブジェクトプロパティをまだ更新できない方法はありますか? (私はコンパイル時に正確なプロパティを知りません)。

人気のある回答

あなたのコンテキストからエンティティ "X"と "Y"を取得した場合、それらはChangeTrackerによって自動的に追跡されます。したがって、 "X"オブジェクトの "Y"プロパティにコンテキストから取得した "Y"インスタンスを割り当て、SaveChangesまたはSaveChangesAsyncを呼び出すと、EntityFrameworkは自動的に処理します。

var x = this.GetX();    
x.Y = "Y1";
await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

通常、オブジェクト "X"のプロパティ "Y"は、それが外部キーであることを示すために仮想でなければなりません。


編集1:

私が正しく理解していれば、実行時に動的にオブジェクトのプロパティを更新し、Web APIからの値を更新したいとします。

第1の方法:

同様に、コンテキストインスタンスに "X"オブジェクトを添付してEntityState.Unchangedでエンティティの追跡を開始し、更新が必要な各プロパティにフラグを立てることができます。

this.mainContext.Xs.Attach(x);
var entry = this.mainContext.entry(x);
entry.Property(p => p.Y).CurrentValue = "Y1";
await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

エンティティをアタッチするときにGraphBehaviorを指定できます。ナビゲーションプロパティを横断するかどうかをEntityFrameworkに指示します。

第2の方法:

DbSet.Update()メソッドの使用:

this.mainContext.Xs.Update(x);
await this.mainContext.SaveChangesAsync().ConfigureAwait(false);

EntityState.Modifiedという状態のエンティティの追跡を自動的に開始します。すべてのプロパティは変更済みとしてマークされます。このメソッドを使用するときは、すべてのプロパティが更新されるため注意が必要です。一部のオブジェクトが "X"オブジェクトで初期化されていない場合、一部のデータが失われる可能性があります。そのような事態を防ぐためには、入力を常に検証する必要があります。


ORMからドメインモデルを分離した状態にしたい場合は、エンティティタイプとドメインタイプを分離する必要があります。 Automapperのようなオブジェクトマッパーを使用してエンティティをドメインタイプにマッピングすることができます。逆もまた同様です。このようにして、データアクセスレイヤーとビジネスロジックレイヤーで行う作業をはっきりと分けることができます。



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ