[NotMapped]
public class AppUser:IdentityUser
{
[Required]
public string RealName { get; set; } = default!;
[Required]
[ForeignKey("DepartmentId")]
public Department Department { get; set; } = default!;
}
public class Department
{
[Key]
public int DepartmentId { get; set; }
[Required]
public string Name { get; set; } = default!;
public Department? Parent { get; set; }
}
if (ModelState.IsValid)
{
var user = new AppUser { UserName = model.UserName, RealName = model.RealName};
var dep = _departmentRepository.Departments.FirstOrDefault(d => d.DepartmentId == Id);
user.Department = dep;
if (model.Password != null)
{
var result = await userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
return RedirectToAction(nameof(Index));
}
}
return View(model);
}
扩展的IdentityUser,增加了Department外键,虽然从主表Departments中找到了实例并赋值给了user的Department属性,但是CreateAsync的时候仍然要在主表Departments中添加此Department实例,怎么解决?急!
引用 皆我百晓生 小程序回复内容作答:
您在扩展的 AppUser
类中添加了 Department
外键属性,并在创建用户时尝试将对应的部门赋值给该属性。然而,即使您已经在主表 Departments
中找到了部门实例并赋值给了 user
的 Department
属性,但 CreateAsync
方法仍会尝试在主表 Departments
中添加该部门实例,导致外键冲突。
要解决这个问题,您可以将外键属性 Department
声明为导航属性,在数据库迁移时设置外键关系。这样,EF Core 将会自动处理外键的关联关系,而不会尝试向主表 Departments
中添加已经存在的部门实例。
您可以按照以下步骤进行修改:
修改 AppUser
类的属性声明,将 Department
改为 DepartmentId
外键属性:
[Required]
[ForeignKey("Department")]
public int DepartmentId { get; set; }
public Department Department { get; set; } = default!;
在数据库上下文中描述 AppUser
类与 Departments
表之间的关系:
protected override void OnModelCreating(ModelBuilder builder)
{
// 其他配置代码...
builder.Entity<AppUser>()
.HasOne(u => u.Department)
.WithMany()
.HasForeignKey(u => u.DepartmentId)
.OnDelete(DeleteBehavior.Restrict);
// 其他配置代码...
}
通过以上修改,EF Core 将会正确处理 AppUser
类与 Departments
表之间的外键关系,而不会尝试在 CreateAsync
方法中向 Departments
表中添加已经存在的部门实例,从而解决外键冲突的问题。
【以下回答由 GPT 生成】
在给user.Department
赋值时,只是将Department
实例赋给了user.Department
属性,并没有在数据库中将该实例插入到Departments
表中。因此,在调用CreateAsync
方法时,会提示主表外键冲突。为了解决这个问题,可以采取以下两种方案之一:
方案一:使用导航属性
在Department
类中添加一个导航属性来关联AppUser
类,然后在创建Department
实例时,将它关联到AppUser
实例上,这样在调用CreateAsync
方法时就不会提示主表外键冲突。
修改AppUser
类:
[NotMapped]
public class AppUser: IdentityUser
{
[Required]
public string RealName { get; set; } = default!;
[Required]
public int DepartmentId { get; set; }
[ForeignKey("DepartmentId")]
public Department Department { get; set; } = default!;
}
修改Department
类:
public class Department
{
[Key]
public int DepartmentId { get; set; }
[Required]
public string Name { get; set; } = default!;
public Department? Parent { get; set; }
public ICollection<AppUser> Users { get; set; } // 添加导航属性
}
修改创建用户的代码:
if (ModelState.IsValid)
{
var user = new AppUser { UserName = model.UserName, RealName = model.RealName };
var dep = _departmentRepository.Departments.FirstOrDefault(d => d.DepartmentId == Id);
user.DepartmentId = dep.DepartmentId; // 使用DepartmentId属性
user.Department = dep;
if (model.Password != null)
{
var result = await userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
return RedirectToAction(nameof(Index));
}
}
return View(model);
}
方案二:手动保存Department实例
在调用CreateAsync
方法前,先将Department
实例保存到Departments
表中。
修改创建用户的代码:
if (ModelState.IsValid)
{
var user = new AppUser { UserName = model.UserName, RealName = model.RealName };
var dep = _departmentRepository.Departments.FirstOrDefault(d => d.DepartmentId == Id);
user.Department = dep;
// 保存Department实例
_departmentRepository.Save(dep);
if (model.Password != null)
{
var result = await userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
return RedirectToAction(nameof(Index));
}
}
return View(model);
}
这里假设有一个_departmentRepository
的仓储类,并且提供了Save
方法来保存Department
实例到数据库中。具体的保存逻辑需要根据你的数据访问层实现来确定。
以上是两种解决方案,你可以根据实际情况选择其中一种来解决你的问题。