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
我想在我的控制器中设置一个布尔值 属性 并将其保存到数据库中。 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