1

変更追跡に CTP5 DBContext を使用して EntityObject と同じ動作を再現しようとしています。テーブル Movie と Director を考えてみましょう。関係は、映画の場合は 1 人の監督のみであり、各監督の場合は複数の映画です。

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 で行われたように、"Association fixup" ロジックを記述する必要がありますか?
  • もしそうなら、DbContext T4 ジェネレーターで Association fixup コードが削除されたのはなぜですか?
4

2 に答える 2

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 プロキシを使用している (つまり、ナビゲーション プロパティを仮想化する) 場合でも実装されません。

于 2011-02-10T22:23:49.310 に答える
0

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

于 2012-04-30T21:23:27.090 に答える