【问题标题】:EF code first - not able to update a database rowEF 代码优先 - 无法更新数据库行
【发布时间】:2010-11-03 21:50:11
【问题描述】:

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

【问题讨论】:

    标签: c# entity-framework ef-code-first


    【解决方案1】:

    @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

    【讨论】:

      【解决方案2】:

      我相信你想Attach你的对象到数据上下文,而不是添加它。

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

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

      【讨论】:

        【解决方案3】:

        这行不行

        datacontext.Users.Add(user);

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

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

        【讨论】:

          【解决方案4】:

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

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

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

          【讨论】:

          • virtual 与延迟加载无关。 virtual 与您想要更改跟踪的时间有关(EF 将创建一个代理类,覆盖所有成员)。
          • 你说得对,那是我的错,这是漫长的一天。感谢您指出我的错误;)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-02-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-23
          • 2012-04-27
          • 2012-08-12
          相关资源
          最近更新 更多