EFCore:简单 属性 更新期间的实体关联错误

EFCore: Entities association error during a simple property update

我想在我的控制器中设置一个布尔值 属性 并将其保存到数据库中。 EF 抛出有关其他甚至未修改的属性的错误。

The association between entities 'User' and 'RequestDetail' with the key value 'System.InvalidOperationException: The association between entities 'User' and 'RequestDetail' with the key value '{Id: 40}' has been severed but the relationship is either marked as 'Required' or is implicitly required because the foreign key is not nullable. If the dependent/child entity should be deleted when a required relationship is severed, then setup the relationship to use cascade deletes.

如果我使用附加参数调用我的方法,它必须更改一个 RequestDetail 记录的 RequestSent 属性,并且效果很好。 但是在没有这个附加参数的情况下调用该方法,它必须在多个 RequestDetail 记录上更改此 属性。这就是它抛出错误的地方。我不修改与用户相关的任何内容。 如果它必须一次处理更多记录,则会抛出此错误。即使我用 FirstOrDefaults() 和立即 SaveChanges() 将 foreach 重写为一段时间,它也会在第二轮抛出错误。

我的方法:

var head = await _ctx.RequestHeads.FirstOrDefaultAsync(x=>x.Id == d.Id);
if (!d.DetailId.HasValue) {
            var details = _ctx.RequestDetails.Include(x=>x.BuyerUser)
                            .Where(x=>x.RequestHeadId == head.Id); 
//not working, always throws an error if it has to modify more than one record
            await details.ForEachAsync(detail => {
                detail.RequestSent = true;
            });
        } else {
            var detail = head.Details.FirstOrDefault(x=>x.Id == d.DetailId.Value); //works ok, always
            detail.RequestSent = true;
        }
        await _ctx.SaveChangesAsync();

我的模特:

public class RequestHead
{
    [Key, MaxLength(15)]
    public string Id { get; set; }
    public DateTime CreateDate { get; set; }
    public int CreateUserId { get; set; }
    [ForeignKey("CreateUserId")]
    public User CreateUser { get; set; }

    public DateTime? AcceptDate { get; set; }
    public int? AcceptUserId { get; set; }
    [ForeignKey("AcceptUserId")]
    public User AcceptUser { get; set; }

    public DateTime? CloseDate { get; set; }
    public int? CloseUserId { get; set; }
    [ForeignKey("CloseUserId")]
    public User CloseUser { get; set; }     
    public int? CloseReason { get; set; }   
    public bool IsArchive { get; set; }

    [MaxLength(8)]
    public string OrganizationCode { get; set; }

    [ForeignKey("OrganizationCode")]
    public Organization Organization { get; set; }

    public virtual ICollection<RequestDetail> Details { get; set; }
    public virtual ICollection<RequestAttachment> Attachments { get; set; }
}

public class RequestDetail
{
    [Key]
    public int Id { get; set; }

    public string RequestHeadId { get; set; }

    [ForeignKey("RequestHeadId")]
    public RequestHead RequestHead { get; set; }

    [MaxLength(20)]
    public string ProductCode { get; set; }

    [ForeignKey("ProductCode")]
    public Product Product { get; set; }
    public string ProductName { get; set; }
    public bool NoProductCode { get; set; }
    public string Description { get; set; }
    public DateTime CreateDate { get; set; }
    public int CreateUserId { get; set; }
    [ForeignKey("CreateUserId")]
    public User CreateUser { get; set; }


    public DateTime? DelegateDate { get; set; }
    public int? DelegateUserId { get; set; }
    [ForeignKey("DelegateUserId")]
    public User DelegateUser { get; set; }


    public int? BuyerUserId { get; set; }
    [ForeignKey("BuyerUserId")]
    public User BuyerUser { get; set; }

    public bool RequestSent { get; set; }
    public virtual ICollection<RequestAttachment> Attachments { get; set; }

}

上下文:

modelBuilder.Entity<RequestHead>()
            .HasOne(r=>r.CreateUser)
            .WithOne().OnDelete(DeleteBehavior.Restrict);
modelBuilder.Entity<RequestHead>()
            .HasMany(r => r.Details)
            .WithOne(x=>x.RequestHead)
            .HasForeignKey(rd => rd.RequestHeadId);
modelBuilder.Entity<RequestDetail>()
            .HasOne(r=>r.CreateUser)
            .WithOne().OnDelete(DeleteBehavior.Restrict);

解决方案是将 RequestDetail<=>User 关系从 WithOne() 更改为 WithMany()。尽管错误消息有些误导,@IvanStoev 的可能解释如下:

I guess with one-to-one the code expects single record, so when the second record with the same FK comes in, they get confused and decided that the record is deleted