1

というとBエンティティを参照するPOCO Aエンティティがあります。私はAが別の存在するBエンティティを参照するようにしたいとします。bbとしましょう。既存のエンティティへの外部キーが参照元エンティティの更新時に保存されていません

これらの手順:

var b = // get existing b from somewhere out-of-context 
var a = new A { B = b } 
dbcontext.Set<B>.Attach(a.B); 
dbcontext.Set<A>.Add(a); 
context.SaveChanges(); 

適切bの主キーIDに設定B_ID外部キーで期待通りaための挿入文を生成します。これらの後続のステップ:

var bb = // get existing bb from somewhere out-of-context 
a.B = bb; 
differentdbcontext.Set<B>.Attach(a.B); 
differentdbcontext.Set<A>.Attach(a); 
differentdbcontext.Entry(a).State = EntityState.Modified; 
differentdbcontext.SaveChanges(); 

この結果、永続化データは変更されません。更新ステートメントには、set B_ID = ...が期待どおりに含まれていません。

私はこれまでのように他のシナリオを持っていたので、何か単純な間違いをしています。

答えて

1

ステートをModifiedに設定すると、スカラープロパティにのみ影響しますが、ナビゲーションプロパティには影響しません。 B_IDはモデルのプロパティではなく、データベースの外部キー列のみがモデルに公開されていないと仮定します。

この場合、Entity Frameworkの自動変更検出を利用することによってのみリレーションシップを更新できます。あなたドン場合

var bb = // get existing bb from somewhere out-of-context 

differentdbcontext.Set<B>().Attach(bb); 
differentdbcontext.Set<A>().Include(x => x.B).Single(x => x.Id == a.Id); 

a.B = bb; 

differentdbcontext.SaveChanges(); 

:一つのアプローチは、 - - と私は標準的なアプローチこれを呼ぶだろう、データベースから元B含むオ​​リジナルAをロードして、新しいbba.Bを設定し、変更内容を保存することですDBからオリジナルをロードしたくない場合、トリックプログラミングが必要です。

var bb = // get existing bb from somewhere out-of-context 

if ( (a.B == null && bb != null) 
    || (a.B != null && bb == null) 
    || (a.B != null && bb != null && a.B.Id != bb.Id)) //take care not to attach 
                 //two objects with same key 
{ 
    if (bb != null) 
     differentdbcontext.Set<B>().Attach(bb); 
    differentdbcontext.Set<A>().Attach(a); 
    a.B = bb; // EF will detect this change 
} 
else if (a.B == null && bb == null) 
{ 
    // create a dummy a.B 
    a.B = new B(); // it doesn't matter which Id 
    differentdbcontext.Set<A>().Attach(a); 
    a.B = bb; // = null -> EF will detect a change 
} 

differentdbcontext.SaveChanges(); 

またはそれに類するものです。その考え方は、変更検出がFK列の更新をデータベースに送信するように、オブジェクトを添付した後に参照を変更することです。

外部キーをプロパティとしてモデルに公開すると、この状況がさらに簡単になります。 Modifiedに状態を設定すると、FKプロパティがスカラーであるために機能します。

+0

クライアントから送信された 'A' DTOの逆シリアル化時に' A.B'が 'bb'に設定されることを明確にする必要があります。したがって、 'differentdbcontext'を使用する前に発生する' A.B 'への実際の割り当てはありません。割り当てを行わずにプロパティを変更したことをEF *に伝える明示的な方法はありますか? – Kit

+0

@Kit:いいえ、ありません。プロパティが変更されたことを明示的にEFに伝えることは、スカラープロパティと複合プロパティに対してのみサポートされ、ナビゲーションプロパティ/リレーションシップに対してはサポートされません。独立した関連の弱点(=外部キーのプロパティなし)と、FKの関連付け(外部キーの公開)がEF 4に導入された主な理由です。 – Slauma

+0

基本的に正しいので回答を受け入れましたが、私がこれをEF上の一般的なリポジトリインターフェースで正しく動作させるには、拷問を進める必要があると考えています。 – Kit

関連する問題