更新和管理实体框架核心

时间:2018-02-07 13:21:42

标签: c# asp.net-mvc asp.net-core entity-framework-core

我正在构建一个ASP.NET核心REST服务器。我需要知道如何正确更新我的实体之间的多对多关系 - 我想通过Entity Framework核心添加,删除和更新链接表中的一些记录。

我的代码:

用户模型

public class User
{
    [Key]
    public int IDUser { get; set; }
    [Required]
    public string Forename { get; set; }
    [Required]
    public string Name { get; set; }
    public string AvatarPath { get; set; }
    public string Email { get; set; }
    public string PhoneNumber { get; set; }
    public string Password { get; set; }
    public User CreatedBy { get; set; }
    public DateTime CreatedAt { get; set; }

    public List<UserPermission> UsersPermissions { get; set; }
}

权限模式

public class Permission
{
    [Key]
    public int IDPermission { get; set; }
    public string Name { get; set; }

    [Required]
    public int IDMachine { get; set; }
    public Machine Machine { get; set; }

    public List<UserPermission> UsersPermissions { get; set; }
}

UserPermission模型 - 用于链接表

public class UserPermission
{
    [Key]
    public int IDUserPermission { get; set; }

    public int IDUser { get; set; }
    public int IDPermission { get; set; }
    public User User { get; set; }
    public Permission Permission { get; set; }
}

的DbContext

public class DBContext : DbContext
{
    public DBContext(DbContextOptions<DBContext> options)
        : base(options)
    {

    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>()
           .HasIndex(u => u.Email)
           .IsUnique();

        modelBuilder.Entity<UserPermission>()
            .HasIndex(bp => new { bp.IDPermission, bp.IDUser })
            .IsUnique();

        modelBuilder.Entity<UserPermission>()
            .HasOne(up => up.User)
            .WithMany(u => u.UsersPermissions)
            .HasForeignKey(up => up.IDUser);

        modelBuilder.Entity<UserPermission>()
            .HasOne(up => up.Permission)
            .WithMany(p => p.UsersPermissions)
            .HasForeignKey(up => up.IDPermission);

        base.OnModelCreating(modelBuilder);
    }

    public DbSet<Machine> Machines { get; set; }
    public DbSet<Permission> Permissions { get; set; }
    public DbSet<User> Users { get; set; }
    public DbSet<UserPermission> UsersPermissions { get; set; }
}

PermissionsController - HttpGet

[HttpGet("{id}", Name = "GetPermissionByID")]
public async Task<IActionResult> GetPermissionByID(Int32 id)
{
    try
    {
        var permission = await _context.Permissions.Include(p => p.UsersPermissions).FirstOrDefaultAsync(s => s.IDPermission == id);

        if (permission == null)
        {
            return NotFound();
        }
        else
        {
            return new ObjectResult(permission);
        }
    }
    catch (Exception ex)
    {
        Helpers.ExceptionLogger.LogException(ex);
        return StatusCode(500);
    }

}

PermissionController - HttpPut

[HttpPut("{id}")]
public async Task<IActionResult> UpdatePermission(int id, [FromBody]Permission permission)
{
    if (permission == null || permission.IDPermission != id)
    {
        return BadRequest();
    }

    try
    {
        var permissionToupdate = await _context.Permissions.Include(p => p.UsersPermissions).AsNoTracking().FirstOrDefaultAsync(u => u.IDPermission == id);
        if (permissionToupdate == null)
        {
            return NotFound();
        }

        permissionToupdate.IDMachine = permission.IDMachine;
        permissionToupdate.IDPermission = permission.IDPermission;
        permissionToupdate.Machine = permission.Machine;
        permissionToupdate.Name = permission.Name;
        permissionToupdate.UsersPermissions = permission.UsersPermissions; // it doesn't actually work

        _context.Permissions.Update(permissionToupdate);
        await _context.SaveChangesAsync();
        return new NoContentResult();
    }
    catch (Exception ex)
    {
        Helpers.ExceptionLogger.LogException(ex);
        return StatusCode(500);
    }
}

当我调用HttpPut操作并尝试更新该行中的UsersPermissions表格permissionToupdate.UsersPermissions = permission.UsersPermissions;时,EF不会向SQL Server生成正确的查询。我希望能够通过修改UsersPermissions导航属性来添加,删除和更新该链接表中的一些记录。我似乎做错了什么或者不明白如何实现这个目标。有人可以指导我有什么选择吗?如何在我的情况下添加,删除和更新链接表?

我不知道有什么好的做法,但我只是想知道:您如何管理实体UsersPermissionsUser之间的链接表Permissions

  • 1)通过专门为该链接表UsersPermissionsController创建单独的控制器UsersPermissions来添加,删除,更新记录?
  • 2)通过更新导航属性Permission.UsersPermissions Permission实体,以便添加,删除,更新记录?

1 个答案:

答案 0 :(得分:2)

您不能只将一个列表替换为另一个列表。由于EF Core使用的更改跟踪,这看起来就像是在初始列表中的所有内容上发布删除,然后添加新列表的所有内容。然后,由于某些“被添加”的实际存在,EF最终会出现冲突的实体状态。

长短,您需要有选择地删除已删除的项目并添加新项目,仅保留现有关系。

permissionToUpdate.UserPermissions
    .Except(permission.UserPermissions)
    .ToList()
    .ForEach(x => permissionToUpdate.UserPermissions.Remove(x));

permission.UserPermissions
    .Except(permissionToUpdate.UserPermissions)
    .ToList()
    .ForEach(x => permissionToUpdate.UserPermissions.Add(x));