2012-04-27 14 views
0

関係を考える:Entity Frameworkの:ChildCollection項目の削除

人1 - *のTelephoneNumber

(人は0、1またはそれ以上のTelephoneNumberエンティティを持っている)

そして、私の統合をテスト:

[TestMethod()] 
    public void DeleteTelephoneNumberAndSavePersonTest() 
    { 
     Person person; 
     using (SopEntities sopEntities = EntitiesFactory.Create(Properties.Resources.ConnectionString)) 
     { 
      PeopleRepository target = new PeopleRepository(sopEntities); 
      person = target.GetPerson(7); 
      Assert.IsTrue(person.TelephoneNumbers.Any()); 
      Assert.AreEqual("DeleteTelephoneNumberAndSavePersonTest", person.TelephoneNumbers.Single().Number); 
      person.TelephoneNumbers.Remove(person.TelephoneNumbers.Single()); 
      target.SavePerson(person); 

      Person savedPerson = target.GetPerson(7); 
      Assert.IsFalse(savedPerson.TelephoneNumbers.Any()); 
     } 
    } 

これは、既に作成された私はこれが本当であることを知っています)Person(ID = 7)はTelephoneNumberコレクション内に1つのTelephoneNumberを持ちます。これは正常に動作します。

私はテストの一環としてTelephoneNumberを削除します。

、次のコードを使用している、それを保存:

public Person SavePerson(Person person) 
     { 
      if (person == null) 
       throw new ArgumentNullException("person"); 


      Person existingPerson= SopEntities.People.Include("EmailAddresses").Include("TelephoneNumbers").Include("WebResources").SingleOrDefault(q => q.ID==person.ID); 
// NOTE: The existingPerson ALREADY has the TelephoneNumber removed, even though retrieved from the DB again. WHY IS THIS? 

// snip: collection reconciliation code 

      SopEntities.SaveChanges(); 
      return existingPerson; 
     } 

私はこの時点で永続化コレクションにインメモリの和解でこの記事をそらすためにしたくないが、あなたを描画したいと思います既存の人の勉強への注意。この人は、これをデバッグするときにTelephoneNumberのコレクションから既にTelephoneNumberを削除しています。

これは、TestMethodの同じエンティティコンテキスト内にあるためです。 TelephoneNumberの読み込みとアイテムの削除の間に新しいコンテキストを作成した場合、取り出されたPersonはTelephoneNumbersコレクションに期待通りのTelephoneNumberを持ちます。

EntityFrameworkは明らかに変更をキャッシュしており、内部コンテキストへの変更を(より良い言葉のために)「投影」しています。私はこれが起こることを望んでいない。

どうすればこの現象を防ぐことができますか?すなわち、私がデータベースコンテンツを求めるとき、EFのDBコンテンツの印象ではなく、データベースコンテンツを欲しいと思います。

+0

私にはあなたの質問はXY問題のようです:あなたはXを達成してYを使って解決しようとしますが、Yはうまくいかず、なぜYが動かないのか、Yを変更して作業。あなたがXに答えると( 'Save'メソッドで未変更の人をロードする目的は何かを説明してください)、より良い答えを得るかもしれません。 – Slauma

+0

申し訳ありませんが、私はあまりにも明確なコードの邪魔な要素を排除していないようです。SopEntitiesの結果からexistingPersonを返すように見えますが、欠落しているコードの一部は、すでに存在するエンティティのイベントで返されたオブジェクトを更新しています。 しかし、これは問題ではありません。問題は、Person.TelephoneNumbersコレクションからTelephoneNumberを削除し、それを送信するとObjectContextから削除されるため、保存中に相違点を調整できないことです。 私のリポジトリパターンが壊れていないと思われます。ご協力いただきありがとうございます。 –

答えて

0

あなたは、EFは、エンティティを添付しようとすることを避けるために追跡無効に変更(ObjectContextためDbContextMergeOption.NoTrackingためAsNoTracking()を使用)と... ...この行に

Person existingPerson= SopEntities.People.... 
    .SingleOrDefault(q => q.ID==person.ID); 

を人をロードしようとすることができますあなたがすでにそれを変更した文脈に移動します。

SavePersonから返されたオブジェクトをチェンジトラッキングに使用し、それをコンテキストにアタッチしたい場合は、役に立たないかもしれません。 EFでは、同じキーを持つ2つの添付オブジェクトを持つことができず、エンティティにすでに適用されているすべての変更を含む、すでにアタッチされているオブジェクトを返します。

私はあなたが何をしたいのか分かりません。あなたのSavePersonメソッドが "以前の"人(あなたがそれを変更する前の状態にいる人)を返すと思われるような感じです。もしそうなら、別のアプローチは、オブジェクトを修正してクローンを返す前にオブジェクトを(深く)クローンすることです。

関連する問題