2010-11-03 134 views
3

正在嘗試使用EF「代碼優先」方法執行某些代碼,並遇到一個奇怪的問題。EF代碼優先 - 無法更新數據庫行

我的DataContext:

public class BookmarkerDataContext : DbContext 
    { 
     public DbSet<User> Users { get; set; } 
     protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder) 
     { 
      modelBuilder.Entity<User>().HasKey(u => u.UserId); 
      base.OnModelCreating(modelBuilder); 
     } 
    } 

當用戶對象是:

public class User 
    { 
     public long UserId { get; set; } 
     public ICollection<Tag> Tags { get; set; } 
    } 

在我的代碼我做的相當簡單的事情:

public void UpdateUserTags(User user,ICollection<Tag> taglist) 
    { 
     user.Tags = new List<Tag>(user.Tags.Union(taglist)); 
     datacontext.Users.Add(user); 
     datacontext.SaveChanges(); 
    } 

用戶對象我傳遞到這個功能是類似的結果:

datacontext.Users.SingleOrDefault(u => u.UserId==id) 

每次我調用UpdateUserTags函數時,它似乎都會在用戶表中創建一個新行,而不是更新它。我在這裏做錯了什麼?

回答

4

@唐納德是正確的,你需要Attach到ObjectContext進行更新時。

但是,那是隻有當你的實體分離。

如果像你這樣的聲音已經從圖中檢索到的單一實體:

var user = datacontext.Users.SingleOrDefault(u => u.UserId==id); 

這意味着你不需要安裝或重新得到它。只是這樣做:

var user = datacontext.Users.SingleOrDefault(u => u.UserId==id); 
user.Tags = new List<Tag>(user.Tags.Union(taglist)); 
context.SaveChanges(); 

不過,我不會建議更換整個標籤收藏,添加標籤:

user.Tags.Add(someTag); 

HTH

0

就不會在此線

datacontext.Users.Add(用戶);

始終將用戶記錄標記爲需要添加到用戶表中。

我認爲你必須從舊的上下文中分離出用戶,並將它附加到新的適當地能夠更新記錄。 但我不是EF英勇所以ymmv

3

我相信你想Attach你的對象到數據上下文,而不是添加它。

public void UpdateUserTags(User user,ICollection<Tag> taglist) 
{ 
    datacontext.Attach(user); 
    user.Tags = new List<Tag>(user.Tags.Union(taglist)); 
    datacontext.SaveChanges(); 
} 

一旦連接,上下文就會知道該對象。一旦你保存了更改,它們應該被保存到數據庫中。

0

這有什麼,與你的具體問題,但對於延遲加載,你會希望標籤須註明虛擬

public virtual ICollection<Tag> Tags { get; set; } 

此外,它看起來像你想添加新的標籤一用戶(或更新他們的標籤),如果是這種情況,那麼你會想要使用附加唐納德建議

+0

'virtual'無關與延遲加載。當您想要更改跟蹤時,「虛擬」與EF相關(EF將創建一個代理類,覆蓋所有成員)。 – RPM1984 2010-11-03 22:34:33

+0

你說得對,那是我的壞事,過了漫長的一天。謝謝你指出我的錯誤;) – PsychoCoder 2010-11-04 01:30:12