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

时间:2018-07-26 08:01:26

标签: c# entity-framework entity-framework-core ef-core-2.1

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

  

实体“用户”和“请求详细信息”之间的关联   键值'System.InvalidOperationException:之间的关联   键值为“ {Id:40}”的实体“ User”和“ RequestDetail”具有   被切断但该关系被标记为“必需”或   隐式要求,因为外键不可为空。如果   必要的关系时,应删除从属/子实体   断开,然后设置关系以使用级联删除。

如果我使用附加参数调用方法,则必须更改一个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);

1 个答案:

答案 0 :(得分:1)

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

  

我猜一对一的代码期望单个记录,所以当   具有相同FK的第二张唱片进来,他们感到困惑并决定   该记录已删除