我正在构建一个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
导航属性来添加,删除和更新该链接表中的一些记录。我似乎做错了什么或者不明白如何实现这个目标。有人可以指导我有什么选择吗?如何在我的情况下添加,删除和更新链接表?
我不知道有什么好的做法,但我只是想知道:您如何管理实体UsersPermissions
和User
之间的链接表Permissions
?
UsersPermissionsController
创建单独的控制器UsersPermissions
来添加,删除,更新记录?Permission.UsersPermissions
Permission
实体,以便添加,删除,更新记录?答案 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));