实体框架保存多对多的更改

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实体框架保存多对多的更改相关的知识,希望对你有一定的参考价值。

我有一个用户1- * UserGroupLinks * -1 UserGroups表结构,并创建了以下方法:

public static string SaveUser(User user, List<UserGroup> newUserGroups)
{
    using (var dbContext = new DCSEntities())
    {       
        var existingUserGroups = user.UserGroups.ToList<UserGroup>();
        existingUserGroups.ForEach(d => user.UserGroups.Remove(d));                
        newUserGroups.ForEach(a => user.UserGroups.Add(a));
        dbContext.ObjectStateManager.ChangeObjectState(user, EntityState.Modified);
        dbContext.SaveChanges();
        return user.UserCode;
    }
}

我想删除该用户的所有usergrouplinks,然后添加新的用户组列表。当我运行此方法时,我在UserGroups对象/ UsergroupLink表上违反了主键,表明我尝试删除现有的用户组链接失败。我该如何解决这个错误?

所以我改变了原始代码以确认怀疑。

public static string SaveUser(User user, List<UserGroup> newUserGroups)
{
    using (var dbContext = new DCSEntities())
    {
        User dbUser = dbContext.Users.Where(u => u.UserCode == user.UserCode).Include(ug => ug.UserGroups).Include(s => s.Status).FirstOrDefault();
        var existingUserGroups = dbUser.UserGroups.ToList<UserGroup>();
        existingUserGroups.ForEach(d => dbUserUserGroups.Remove(d));   
        newUserGroups.ForEach(a => dbContext.UserGroups.Attach(a));
        newUserGroups.ForEach(a => dbUser.UserGroups.Add(a));
        dbContext.ObjectStateManager.ChangeObjectState(dbUser, EntityState.Modified);
        dbContext.SaveChanges();
        return dbUser.UserCode;
    }
}

我可以确认的是,此代码仅在为该用户添加新组时才有效。只要您尝试添加现有组,它就会提供主键违规。这几乎就好了

existingUserGroups.ForEach(d => dbUserUserGroups.Remove(d)); 

没有生效。我的解决方案不优雅,因此我没有将其标记为答案。

答案

使用2个不同dbcontexts的想法实际上有效,但根据我上面的评论,我不认为这是一个优雅或正确的解决方案:

public static string SaveUser(User user, List<UserGroup> newUserGroups)
{
    using (var dbContext = new DCSEntities())
    {
        User dbUser = dbContext.Users.Where(u => u.UserCode == user.UserCode).Include(ug => ug.UserGroups).Include(s => s.Status).FirstOrDefault();
        var existingUserGroups = dbUser.UserGroups.ToList<UserGroup>();
        existingUserGroups.ForEach(d => dbContext.UserGroups.Detach(d));
        existingUserGroups.ForEach(d => dbUser.UserGroups.Remove(d));
        dbContext.ObjectStateManager.ChangeObjectState(dbUser, EntityState.Modified);
        dbContext.SaveChanges();
    }

    using (var dbContext = new DCSEntities())
    {
        User dbUser = dbContext.Users.Where(u => u.UserCode == user.UserCode).Include(ug => ug.UserGroups).Include(s => s.Status).FirstOrDefault();
        newUserGroups.ForEach(a => dbContext.UserGroups.Attach(a));
        newUserGroups.ForEach(a => dbUser.UserGroups.Add(a));
        dbContext.ObjectStateManager.ChangeObjectState(dbUser, EntityState.Modified);
        dbContext.SaveChanges();
        return dbUser.UserCode;
    }
}

我甚至逐字复制这个解决方案,仍然遇到了主要密钥违规问题entity framework update many to many relationship: virtual or not

如果有人能解释为什么我需要用2种不同的语境来做这件事我会非常感激。感谢名单

以上是关于实体框架保存多对多的更改的主要内容,如果未能解决你的问题,请参考以下文章

实体框架代码优先的多对多关系的最佳方法

代码第一个约定不在实体框架6.2中的多对多关系上创建连接表

实体框架使用 Codefirst、通用存储库、工作单元模式保存多对多关系

多对多实体框架和存储库模式插入/更新

关于JPA一对一,一对多(多对一),多对多的详解

(转)Hibernate框架基础——多对多关联关系映射