微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

EF Core 5 一对多关系问题

如何解决EF Core 5 一对多关系问题

在这个例子中,一个用户有零张或多张账单,一张账单可以分配给一个用户。帐单也可以创建但从不分配。

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 中,我希望有一种方法可以让我更新/添加账单并将其分配给用户

如果数据库中不存在该用户,则应添加用户。如果用户存在,它应该更新它。

我尝试了两种方法。 第一:

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 是同一个类。

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;

因为您刚刚将实体附加到上下文并更新/插入它。

另外,不要忘记格式化您的代码,例如 https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/inside-a-program/coding-conventions

考虑不直接从模型插入/更新实体会很有用,例如:

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您的工作。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。