2010-11-03 133 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