【问题标题】:Facing issue with Entity framework Db approach实体框架 Db 方法面临的问题
【发布时间】:2022-09-24 09:07:23
【问题描述】:

我有这些课程

public class UserRole
{
      public int RoleId { get; set; }
      public int UserId { get; set: }
      public virtual User User { get; set; }
      public virtual Role Role { get; set; }
}

[Table(\"User\")]
public class User
{
    public User()
    {
        UserRoles = new HashSet<UserRole>();
    }

    public int FirstName { get; set; }
    public int UserId { get; set: }

    public virtual ICollection<UserRole> UserRoles { get; set; }
}

[Table(\"Role\")]
public class Role
{
    public Role()
    { 
        UserRoles = new HashSet<UserRole>();
    }

    public int RoleId { get; set; }
    public string RoleName { get; set; }

    public virtual ICollection<UserRole> UserRoles { get; set; }
}

我正在尝试对UserRole 表进行简单插入

public class Run
{
   DbContext context;

   public Run()
   {
       context = new DbContext();
   }

   public void Validate(User user, int roleId)
   { 
       InsertUserRole(user,roleId)
       context.SaveChanges();
   }
}
   
public void InsertUserRole(user targetUser, int roleId)
{
    UserRole targetUserRole = targetUser.UserRoles
                                        .Where(u => u.RoleId == roleId)
                                        .FirstOrDefault();

    if (targetUserRole == null)
    {
        targetUserRole = new UserRole();
        targetUserRole.RoleId = roleId;
        targetUserRole.UserId = targetUser.UserId;

        context.UserRoles.Add(targetUserRole);
    }
}

当我尝试插入 UserRole 表时,我得到一个异常

违反唯一键 \'UQ_Role_Name\'。无法在 dbo.Role 中插入重复键

我需要在UserRole 中插入行,因为用户不存在该角色,并且该角色存在于Role 表中。

请让我知道如何使用实体框架上下文插入Userole

  • 这真的是引发异常的确切代码吗?我问是因为 userRole targetUserRole 无法编译(应该是 UserRole targetUserRole 并且您显示的代码应该没问题,但实际上 EF 尝试将现有的 Role 插入数据库中。
  • @GertArnold是的,它是UserRole targetUserRole。如何停止插入Role表并仅插入UserRole,因为它存在于Role表中,我们应该只插入UserRole表。

标签: entity-framework entity-framework-6 ef-database-first


【解决方案1】:

我不确定是否有足够的关于您的实体/架构的信息来缩小问题的具体原因,但我确实想到了一些事情。

首先,您如何为 UserRole 实体提名 PK?这应该通过实体中的属性或通过实体配置来完成:

public class UserRole
{
    [Key, Column(Order=0), ForeignKey("User")]
    public int UserId { get; set; }
    [Key, Column(Order=1), ForeignKey("Role")]
    public int RoleId { get; set; }

    public virtual User User { get; set; }
    public virtual Role Role { get; set; }
}

接下来,要添加一个新的 UserRole,应该可以通过设置 ID 来实现,但通常我建议设置导航属性而不是 ID。这样做的原因是这会验证您传递的值,并且实体在保存后应该被认为是“完整的”(导航属性可用)。

对于您的 InsertUserRole 方法,有一些调整。您不需要加载现有实体,一个简单的存在检查就足够且更快,然后加载相关引用。这可以插入到 UserRole DBSet 中,也可以添加到请求的用户中:

public void InsertUserRole(int userId, int roleId)
{
    var userRoleExists = context.UserRoles.Any(x => x.UserId == userId && x.RoleId == roleId);

    if(userRoleExists) return;

    var user = context.Users.Single(x => x.UserId == userId);
    var role = context.Roles.Single(x => x.RoleId == roleId);

    UserRole userRole = new UserRole
    {
        User = user,
        Role = role
    };
    context.UserRoles.Add(userRole);
    context.SaveChanges();
}

或者:

public void InsertUserRole(int userId, int roleId)
{
    var user = context.Users
        .Include(x => x.UserRoles)
        .Single(x => x.UserId == userId);

    if(user.UserRoles.Any(x => x.RoleId == roleId) return;

    var role = context.Roles.Single(x => x.RoleId == roleId);

    UserRole userRole = new UserRole
    {
        User = user,
        Role = role
    };
    user.UserRoles.Add(userRole);
    context.SaveChanges();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 1970-01-01
    • 2011-03-09
    • 2013-07-17
    • 1970-01-01
    相关资源
    最近更新 更多