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

Per*_*ier 6 c# entity-framework entity-framework-core ef-core-2.1

我想在我的控制器中设置一个 bool 属性并将其保存到数据库中。EF 会引发有关其他甚至未修改的属性的错误。

实体“User”和“RequestDetail”与键值为“System.InvalidOperationException”之间的关联:实体“User”和“RequestDetail”与键值为“{Id: 40}”之间的关联已被切断,但关系是标记为“必需”或隐式必需,因为外键不可为空。如果在切断所需关系时应删除依赖/子实体,则将关系设置为使用级联删除。

如果我用一个附加参数调用我的方法,它必须更改一个 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();
Run Code Online (Sandbox Code Playgroud)

我的模型:

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; }

}
Run Code Online (Sandbox Code Playgroud)

语境:

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);
Run Code Online (Sandbox Code Playgroud)

Per*_*ier 5

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

我猜一对一的代码需要单条记录,所以当第二条具有相同 FK 的记录进来时,他们会感到困惑并决定删除该记录