EFCore:简单属性更新期间的实体关联错误
Posted
技术标签:
【中文标题】EFCore:简单属性更新期间的实体关联错误【英文标题】:EFCore: Entities association error during a simple property update 【发布时间】:2019-01-03 03:43:22 【问题描述】:我想在我的控制器中设置一个 bool 属性并将其保存到数据库中。 EF 会抛出一个关于其他甚至没有被修改的属性的错误。
实体 'User' 和 'RequestDetail' 之间的关联与 key value '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);
【问题讨论】:
不确定是否相关,但User
关系中的两个.WithOne()
看起来非常可疑。他们可能应该是.WithMany()
。另一个区别是“非工作”查询包含.Include(x=>x.BuyerUser)
。
@IvanStoev Include(x=>x.BuyerUser) 只是一个测试,如果问题可能是导航属性未加载。 .WithOne() 但是,我确信这一定是我的上下文配置中的内容。谢谢!
嗯,大多数 EF 消息......令人困惑 :) 我可以忍受(他们有很多功能要做,所以我猜消息是最低优先级)。行为怎么样,我猜一对一的代码需要单个记录,所以当第二个具有相同 FK 的记录进入时,他们会感到困惑并决定删除该记录:) 只是一个猜测 - 实际代码相当复杂。
@IvanStoev 您介意将其发布为答案,以便我可以关闭此问题吗?
没有时间撰写一个好的答案。请随时发布自我答案。很高兴它有帮助,编码愉快。
【参考方案1】:
解决方案是将 RequestDetail用户关系从 WithOne() 更改为 WithMany()。尽管错误消息有些误导,但@IvanStoev 的可能解释如下:
我猜一对一的代码需要单个记录,所以当 相同FK的第二张唱片进来了,他们感到困惑并决定 记录被删除
【讨论】:
以上是关于EFCore:简单属性更新期间的实体关联错误的主要内容,如果未能解决你的问题,请参考以下文章