使用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函数时,它似乎在User表中创建一个新的Row而不是更新它。我在这里做错了吗?
答案 0 :(得分:4)
@Donald是正确的,在进行更新时需要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
答案 1 :(得分:3)
我相信你想要Attach你的对象到数据上下文,而不是添加它。
public void UpdateUserTags(User user,ICollection<Tag> taglist)
{
datacontext.Attach(user);
user.Tags = new List<Tag>(user.Tags.Union(taglist));
datacontext.SaveChanges();
}
连接后,上下文就会知道对象。保存更改后,应将其保留到数据库中。
答案 2 :(得分:0)
不会这一行
datacontext.Users.Add(用户);
始终将用户记录标记为需要添加到users表。
我认为你必须从旧的上下文中删除用户并将其附加到新的正确能够更新记录。 但我不是EF,所以ymmv
答案 3 :(得分:0)
这与您的特定问题无关,但对于延迟加载,您希望将标记标记为虚拟
public virtual ICollection<Tag> Tags { get; set; }
此外,看起来您正在尝试为用户添加新标签(或更新其标签),如果是这种情况,那么您将要使用附加为唐纳德建议