3

正在使用 EF“代码优先”方法尝试一些代码,但遇到了一个奇怪的问题。

我的数据上下文:

    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 表中创建一个新行而不是更新它。我在这里做错了吗?

4

4 回答 4

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);

高温高压

于 2010-11-03T22:37:26.243 回答
3

我相信您想将对象附加到数据上下文,而不是添加它。

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

一旦它被附加,上下文就会意识到这个对象。保存更改后,它们应该被持久化到数据库中。

于 2010-11-03T21:57:35.937 回答
0

这行不行吗

数据上下文。用户。添加(用户);

始终将用户记录标记为需要添加到用户表中。

我认为您必须从旧上下文中分离用户并将其附加到新上下文才能正确更新记录。但我不是 EF 怪人,所以 ymmv

于 2010-11-03T21:57:13.203 回答
0

这与您的特定问题无关,但对于延迟加载,您需要将标签标记为虚拟

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

此外,如果是这种情况,您似乎正在尝试为用户添加新标签(或更新他们的标签),那么您将要按照 Donald 的建议使用 Attach

于 2010-11-03T22:13:16.843 回答