代码之家  ›  专栏  ›  技术社区  ›  Perrier

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

  •  1
  • Perrier  · 技术社区  · 6 年前

    我想在控制器中设置一个bool属性并将其保存到数据库。EF抛出一个关于其他属性的错误,这些属性甚至没有被修改。

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

    如果我用一个附加参数调用我的方法,它必须更改一个RequestDetail记录的RequestSent属性,这非常有效。 但是,在不使用此附加参数的情况下调用方法时,必须更改多个RequestDetail记录的此属性。这就是它抛出错误的地方。我不会修改任何与用户相关的内容。 如果它必须一次做更多的记录,它就会抛出这个错误。即使我用FirstOrDefaults()和immediate 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 回复  |  直到 6 年前
        1
  •  1
  •   Perrier    6 年前

    解决方案是将RequestDetail<=>用户关系从WithOne()更改为WithMany()。尽管错误信息有些误导,但@IvanStoev可能会给出以下解释:

    我想一对一的代码需要一条记录,所以当 第二张和同一个FK的唱片进来了,他们很困惑,决定 记录被删除