实体框架不会对数据库进行多对多的关系更改

时间:2014-08-15 20:28:42

标签: c# entity-framework entity-framework-6

我有一个实体ApplicationUser,其中有一个ICollection另一个实体Brand。在我的单元测试中,我向Brand添加了ICollection,我调用了SaveChanges(),但没有任何内容写入我的联结表。

以下是一些代码:

ApplicationUser:

public class ApplicationUser : IdentityUser
    {
        [Required]
        [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 2)]
        [DataType(DataType.Text)]
        public string FirstName { get; set; }
        [Required]
        [StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 2)]
        [DataType(DataType.Text)]
        public string LastName { get; set; }

        public virtual ICollection<Brand> Brands { get; set; }

        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
        {
            // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            // Add custom user claims here
            return userIdentity;
        }
    }

这是品牌

public class Brand
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public virtual ICollection<Product> Products { get; set; }
        public virtual ICollection<ApplicationUser> Users { get; set; }

        public Brand()
        {
            Products = new List<Product>();
            Users = new List<ApplicationUser>();
        }
    }

这是我的联结表的映射

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<ApplicationUser>()
                .HasMany(b => b.Brands)
                .WithMany(n => n.Users)
                .Map(m =>
                {
                    m.MapLeftKey("AspNetUsers.Id");
                    m.MapRightKey("Brand.Id");
                    m.ToTable("UserToBrand");
                });
        }

这是我尝试将更改写入db

的地方
public void UpdateUserInformation(ApplicationUser user)
        {
            using(ApplicationDbContext db = new ApplicationDbContext())
            {
                db.Database.Log = Console.WriteLine;
                db.Users.Attach(user);
                db.Entry(user).State = System.Data.Entity.EntityState.Modified;
                foreach(Brand b in user.Brands)
                {
                    db.Brands.Attach(b);
                    db.Entry(b).State = System.Data.Entity.EntityState.Modified;
                }
                db.SaveChanges();
            }
        }

输出数据库日志后,我可以看到AspNetUser表和Brand表的更新SQL,但UserToBrand表没有。

1 个答案:

答案 0 :(得分:3)

使用断开连接的对象时,需要手动管理同步,包括关系状态。

您需要先从上下文中获取对象,以使所有内容保持同步。

var userDb = db.Users.Find(user.Id);
// Updates scalar properties.
db.Entry(userDb).CurrentValues.SetValues(user);
foreach(Brand b in user.Brands)
{
    // Is still required to prevent EF adds new brand.
    db.Entry(b).State = EntityState.Modified;
    userDb.Brands.Add(b);
}
db.SaveChanges();

或者,如果您确实想要使用断开连接的对象,则需要手动创建关系。

db.Entry(user).State = EntityState.Modified;
foreach(Brand b in user.Brands)
{
    db.Entry(b).State = System.Data.Entity.EntityState.Modified;
    (IObjectContextAdapter)db).ObjectContext.ObjectStateManager
       .ChangeRelationshipState(user, b, u => u.Brands, EntityState.Added);
}
db.SaveChanges();

顺便说一下,Attach方法是多余的,因为它与将状态更改为EntityState.Unchanged相同,然后在附加后再将其更改为EntityState.Modified

更多