2011-02-10 3 views
1

変更トラッキングのためにCTP5 DBContextを使用してEntityObjectと同じ動作を再現しようとしています。ムービーとディレクターのテーブルを考えてみましょう。関係は映画のための1つのディレクターおよび各ディレクターのための複数の映画だけである。EntityFramework CTP5変更トラッキング

var movie = new Movie(); 
      movie.Name = "ABCD"; 
      ctx.Movies.Add(movie);//ctx.Movies.AddObject(movie); 
      movie.Director = new Director() { Name = "dir1" }; 
      var existingDirector = ctx.Directors.Where(a => a.Name == "dir2").FirstOrDefault(); 
      movie.Director = existingDirector; 
      ctx.SaveChanges(); 

これをEntityObjectを使用して実行すると、このコードは変更が追跡されるときに新しいディレクター「dir1」を作成します。 CTP 5 DbContextジェネレータを使用してこのコードを実行すると、新しいディレクタ "dir1"は作成されません。 MovieとDirectorオブジェクトの両方でプロパティーを仮想に変更しました。以下はコードです。

public partial class Director 
{ 
    public Director() 
    { 
     //this.Movies = new HashSet<Movie>(); 
    } 

    // Primitive properties 

    public virtual int DirectorId { get; set; } 
    public virtual string Name { get; set; } 

    // Navigation properties 

    public virtual ICollection<Movie> Movies { get; set; } 

} 
public partial class Movie 
{ 
    public Movie() 
    { 
     //this.Actors = new HashSet<Actor>(); 
    } 

    // Primitive properties 

    public virtual int MovieId { get; set; } 
    public virtual Nullable<int> DirectorId { get; set; } 
    public virtual string Name { get; set; } 

    // Navigation properties 

    public virtual Director Director { get; set; }  
} 

私には3つの質問があります。

  • ここに何か不足していますか?私はすべてのプロパティのために "仮想"を保っていましたが、オブジェクトは追跡されていません。どうして?
  • EF4 POCOで行われたように、「関連付けの修正」ロジックを記述する必要がありますか?
  • もしそうなら、なぜDbContext T4ジェネレータでAssociation fixupコードが削除されたのですか?もちろん

答えて

1

新監督は、あなたのコード内のいくつかの後の時点で、既存のものに新しい映画のディレクターを変更したため、これを試してみてください、あなたはそれらの両方をDBに保存されてますよ保存されません。

var movie = new Movie(); 
movie.Name = "ABCD"; 
ctx.Movies.Add(movie); 
movie.Director = new Director() { Name = "dir1" };  
//movie.Director = existingDirector; 
ctx.SaveChanges(); 

あなた自身のアソシエーションフィックスアップロジックを書くことはできますが、それはあなたのアソシエーションのエンドポイントを同期させておくことになります。ここで示したコードとは関係ありません。

EntityObjectsを使用するときにコードが新しいディレクターをDBに保存する理由は、Relationship Spanという概念が原因です。リレーションシップスパンは、別の添付エンティティに結合したときにObjectContextがエンティティを自動的にアタッチすることを定義します( )。そのデタッチされたオブジェクトが新しい場合、コンテキストにアタッチされるとEntityStateが追加されます。ただし、POCOプロキシを使用している場合(つまり、ナビゲーションプロパティを仮想にする場合)にも、このリレーションシップスパンの動作は実装されません。

+0

コードはダムですが、EntityObjectとDbContext T4ジェネレータの間に相違があることを示したいと思います。要点はEntityObjectジェネレータで同じコード(行コメントなし)がPOCOまたはDbContextジェネレータではなくdbで "dir1"を作成する点です。どうして?トラッキングを変更するとどうなりますか? – Jonna

+0

最新の回答をお読みください。 –

0

私は、これはあなたがそれが期待どおりに動作していないという理由はあなたではなく動的プロキシよりも、(すなわち、new演算子を使用して)Movieクラス自体のインスタンスを作成しているということだと思います。 Movieクラス自体には、変更トラッキングが組み込まれていません。したがって、Directorプロパティを設定すると、通知はDbContextに送信されません。 MovieをDbContextに追加したにもかかわらず、プロキシではなく元のオブジェクトを参照しています。私はあなたがDbSet.Create()(http://msdn.microsoft.com/en-us/library/gg696685(v=vs.103).aspx)を使用してオブジェクトを作成した場合、それは動作すると思います。

関連する問題