2011-02-10 119 views
1

我想重現與使用CTP5 DBContext進行更改跟蹤的EntityObject相同的行爲。考慮表格電影和導演。關係只有一位電影導演和每位導演多部電影。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生成器中刪除了關聯修復代碼?

回答

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時,您的代碼將新導演保存到數據庫中的原因是因爲一個概念,稱爲關係跨度。關係範圍定義了ObjectContext將在您將它添加到另一個附屬實體時自動附加一個實體。如果那個分離的對象是新的,當它被附加到上下文時,它的EntityState將被添加。但是,即使您使用POCO代理(即使您的導航屬性爲虛擬),此關係跨度行爲也未實現。

+0

該代碼是愚蠢的,但我想顯示EntityObject和DbContext T4生成器之間的差異。重點是與EntityObject生成器相同的代碼(沒有註釋行)在db中創建「dir1」,而POCO或DbContext生成器不創建。爲什麼?更改跟蹤發生了什麼? – Jonna 2011-02-10 22:47:13

0

我認爲這不符合你期望的原因是你正在創建一個Movie類的實例本身(即使用new運算符),而不是動態代理。 Movie類本身沒有內置的變化追蹤。因此,當您設置Director屬性時,不會將通知發送到DbContext。即使您將Movie添加到DbContext,仍然引用原始對象,而不是代理。我認爲如果你使用DbSet.Create()創建對象(http://msdn.microsoft.com/en-us/library/gg696685(v=vs.103).aspx),它會工作。