EF Core 5 一对多关系问题
EF Core 5 One-to-many relationship problem
在这个例子中,一个用户有零个或多个账单,一张账单可以分配给一个用户。帐单也可以创建但永远不会分配。
public class User
{
public int Id{ get; set; }
public List<Bill> bills{ get; set; }
}
public class Bill
{
public int Id { get; set; }
public int userId{ get; set; }
public User user{ get; set; }
}
我还在我的数据库上下文配置中添加了这个:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Bill>()
.HasOne(b => b.user)
.WithMany(u => u.bills)
.HasForeignKey(b => b.userId);
}
我是通过工作单元+存储库模式实现的。在我的 BillService.cs
中,我希望有一种方法允许我 update/add 账单并将其分配给用户。
如果数据库中不存在该用户,则应添加该用户。如果用户存在,它应该更新它。
我试过两种方法。
第一:
public async Task<void> AddUpdateBill(AddBillModel model){
Bill bill= await unitOfWork.BillRepository.GetByID(model.billId);
if( unitOfWork.UserRepo.GetById(model.userId) == null){
unitOfWork.UserRepo.Insert(model.user);
}else{
unitOfWork.UserRepo.Update(model.user);
}
bill.user = model.user;
unitOfWork.BillRepository.Update(bill);
unitOfWork.Save();
}
第二个:
public async Task<void> AddUpdateBill(AddBillModel model)
{
Bill bill= await unitOfWork.BillRepository.GetByID(model.billId);
bill.user = model.user;
unitOfWork.BillRepository.Update(bill);
unitOfWork.Save();
}
在这两种情况下,我都遇到了重复主键或已跟踪实体的问题。
最好的方法或正确的方法是什么?
编辑:抱歉,BillRepo 和 BillRepository 相同 class。
public async Task<Bill> GetByID(int id)
{
return await context
.bill
.Include(b => b.user)
.Where(b=> b.id == id)
.FirstOrDefaultAsync();
}
public void Update(Bill bill)
{
context.Entry(bill).CurrentValues.SetValues(bill);
}
第一种方法(对我来说)似乎更正确。
首先,遵守命名规则:所有属性必须以大写字符开头。在您的案例中为“账单”、“用户 ID”、“用户”。
if( unitOfWork.UserRepo.GetById(model.userId) == null){
unitOfWork.UserRepo.Insert(model.user);
}else{
unitOfWork.UserRepo.Update(model.user);
}
bill.user = model.user;
这里不需要
bill.user = model.user;
因为您刚刚将您的实体附加到上下文并且 updated/inserted 它。
此外,不要忘记格式化您的代码,例如 https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/inside-a-program/coding-conventions
考虑 inserting/updating 您的实体不是直接来自模型会很有用,例如:
if( unitOfWork.UserRepo.GetById(model.userId) == null){
var user = new User
{
//set properties
};
unitOfWork.UserRepo.Insert(user);
unitOfWork.Save();
bill.userId = user.Id;
}
这里:
if( unitOfWork.UserRepo.GetById(model.userId) == null){...
您从 UserRepo 检索了用户,但没有将其分配给任何变量。这可能会导致异常指出有多个具有相同ID的被跟踪实体。
尝试检索(包括账单)或创建用户实体并在其中添加新账单。然后将用户实体插入数据库(如果它不存在)并简单地 Save
你的工作。
在这个例子中,一个用户有零个或多个账单,一张账单可以分配给一个用户。帐单也可以创建但永远不会分配。
public class User
{
public int Id{ get; set; }
public List<Bill> bills{ get; set; }
}
public class Bill
{
public int Id { get; set; }
public int userId{ get; set; }
public User user{ get; set; }
}
我还在我的数据库上下文配置中添加了这个:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Bill>()
.HasOne(b => b.user)
.WithMany(u => u.bills)
.HasForeignKey(b => b.userId);
}
我是通过工作单元+存储库模式实现的。在我的 BillService.cs
中,我希望有一种方法允许我 update/add 账单并将其分配给用户。
如果数据库中不存在该用户,则应添加该用户。如果用户存在,它应该更新它。
我试过两种方法。 第一:
public async Task<void> AddUpdateBill(AddBillModel model){
Bill bill= await unitOfWork.BillRepository.GetByID(model.billId);
if( unitOfWork.UserRepo.GetById(model.userId) == null){
unitOfWork.UserRepo.Insert(model.user);
}else{
unitOfWork.UserRepo.Update(model.user);
}
bill.user = model.user;
unitOfWork.BillRepository.Update(bill);
unitOfWork.Save();
}
第二个:
public async Task<void> AddUpdateBill(AddBillModel model)
{
Bill bill= await unitOfWork.BillRepository.GetByID(model.billId);
bill.user = model.user;
unitOfWork.BillRepository.Update(bill);
unitOfWork.Save();
}
在这两种情况下,我都遇到了重复主键或已跟踪实体的问题。
最好的方法或正确的方法是什么?
编辑:抱歉,BillRepo 和 BillRepository 相同 class。
public async Task<Bill> GetByID(int id)
{
return await context
.bill
.Include(b => b.user)
.Where(b=> b.id == id)
.FirstOrDefaultAsync();
}
public void Update(Bill bill)
{
context.Entry(bill).CurrentValues.SetValues(bill);
}
第一种方法(对我来说)似乎更正确。 首先,遵守命名规则:所有属性必须以大写字符开头。在您的案例中为“账单”、“用户 ID”、“用户”。
if( unitOfWork.UserRepo.GetById(model.userId) == null){
unitOfWork.UserRepo.Insert(model.user);
}else{
unitOfWork.UserRepo.Update(model.user);
}
bill.user = model.user;
这里不需要
bill.user = model.user;
因为您刚刚将您的实体附加到上下文并且 updated/inserted 它。
此外,不要忘记格式化您的代码,例如 https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/inside-a-program/coding-conventions
考虑 inserting/updating 您的实体不是直接来自模型会很有用,例如:
if( unitOfWork.UserRepo.GetById(model.userId) == null){
var user = new User
{
//set properties
};
unitOfWork.UserRepo.Insert(user);
unitOfWork.Save();
bill.userId = user.Id;
}
这里:
if( unitOfWork.UserRepo.GetById(model.userId) == null){...
您从 UserRepo 检索了用户,但没有将其分配给任何变量。这可能会导致异常指出有多个具有相同ID的被跟踪实体。
尝试检索(包括账单)或创建用户实体并在其中添加新账单。然后将用户实体插入数据库(如果它不存在)并简单地 Save
你的工作。