1

要するに、なぜこれが失敗するのですか (myChildObjectはデータベースに追加されません)。ObjectContext で動作することに注意してください

using (var db = new dbEntities())
{
    var myParentObject = db.parentObjects.First(); // this definitely exists in the db

    // this **should** attach myChildObject to the context, 
    // and therefore add it to the db on .SaveChanges() - it doesn't!
    var myChildObject = new childObject(){
        parentObject = myParentObject
    };

    db.SaveChanges();
}

このMSDNブログの投稿は言う

すでに追跡されている別のエンティティにフックすることで、新しいエンティティをコンテキストに追加できます。これは、新しいエンティティを別のエンティティのコレクション ナビゲーション プロパティに追加するか、別のエンティティの参照ナビゲーション プロパティを新しいエンティティを指すように設定することによって行うことができます。

追跡対象のオブジェクトをmyChildObject参照しているため、上記のコードは確実に機能するはずです。EF は、コレクションmyParentObjectに追加する必要があることを理解するのに十分なほど賢くある必要があります。childObjectsObjectContext を使用していたときは問題なく動作しましたが、dbContext で動作させるにはすべてのコードを書き直す必要があることがわかりました。

それを機能させるには、次のように書き直す必要があります。

using (var db = new dbEntities())
{
    var myParentObject = db.parentObjects.First(); // this definitely exists in the db

    var myChildObject = new childObject();

    myParentObject.childObjects.Add(myChildObject);

    db.SaveChanges();
}
4

2 に答える 2

1

POCOエンティティを使用しObjectContextていた場合、実際に機能しました。ただし、EF の変更追跡の動作が EF の変更追跡とは異なるためではDbContextなく、EF 4 T4 テンプレートによって生成された POCO エンティティに「関係修正」メソッドが含まれていたためです。

基本的に、行のプロパティ セッターはparentObject = myParentObjectオブジェクトの割り当てだけではありませんでしたが、セッターには、現在手動​​で行っていることを最終的に正確に実行するメソッドへの呼び出しが含まれていましたmyParentObject.childObjects.Add(myChildObject)。この時点で、「既に追跡されている別のエンティティに接続することで、コンテキストに新しいエンティティを追加できます」というルールが適用myChildObjectされ、コンテキストに追加され、データベースに挿入されます。

これらのフィックスアップ メソッドの POCO エンティティを生成する T4 テンプレートはDbContext、他のシナリオで問題を引き起こしていたため、削除されました。特に、遅延読み込みが参照割り当てに関係myParentObject.childObjects...し、プロパティ セッターでの自動呼び出しがコレクションの遅延読み込みをトリガーし、新しい子がコレクションに追加される前に、childObjects既に格納されているすべてを最初に読み込みます。myParentObjectそれらが何千もある場合、これは巨大な不要なオーバーヘッドであり、パフォーマンスは悲惨なものになり、パフォーマンスが突然低下した理由 (単一の参照プロパティを割り当てたという理由だけで) は、背後で実行される修正メソッドを認識していない場合、検出するのは容易ではありません。シーン。

ここここここここは、関係の修正方法が引き起こした混乱の例です。

T4 テンプレートを変更してリレーションシップ修正メソッド再度追加するか、Code-First を使用している場合は、エンティティ クラスに手動で記述するだけで、古い動作を取り戻すことができます。しかし、これは、最後のコード スニペットで概説した方法で既存のコードを変更するよりも複雑で、少なくとも同じくらい多くの作業が必要になる可能性があります。

于 2013-06-07T20:30:47.830 に答える