更新:直到我创建此帖子导致插入失败后,我才看到代码。现在一切正常。不好意思,谢谢您花时间帮助我。
我遇到一个问题,其中EF试图更新不存在的记录。我需要插入记录。
下面的示例代码:
DoStuff(List<ParentObj> listParent, List<OtherParent> listOtherParent)
{
foreach(var op in otherParent)
{
var updateThisParentRecord = listParent.FirstOrDefault(x => x.Id == op.Id);
if(updateThisParentRecord != null)
{
updateThisParentRecord.ChildRecordList.Add(new ChildRecord
{
//set relevant props not PK as it is an identity column
OtherChildObject = new OtherChildObject
{
//set relevant props not PK as it is an identity column
}
});
}
}
await _parentObjectContext.SaveChangesAsync();
}
型号代码:
public partial class ParentObj
{
public ParentObj()
{
ChiledRecordList = new HashSet<ChildRecord>();
}
public int Id {get;set;}
public virtual ICollection<ChildRecord> ChildRecordList {get;set;}
}
public partial class ChildRecord
{
public int Id {get;set;}
public int ParentId {get;set;}
public int OtherChildObject {get;set;}
public virtual OtherChildObject OtherChildObject {get;set;}
public virtual ParentObj {get;set;}
}
public partial class OtherChildObject
{
public OtherChildObj()
{
ParentObj = new HashSet<ParentObj>();
ChildRecord = new Hashset<ChildRecord>();
}
public long Id {get;set;}
//now that I have written this out, the below line seems strange and may
//be keyed wrong?
public virtual ICollection<ParentObj> ParentObj {get;set;}
public virtual ICollection<ChildRecord> ChildRecord {get;set;}
}
保存时会引发以下异常:
“数据库操作预期会影响1行,但实际上会影响0行。 自加载实体以来,数据可能已被修改或删除。 有关了解和处理乐观并发异常的信息,请参见http://go.microsoft.com/fwlink/?LinkId=527962。
这是例外条目列表中的内容:{{Id:1000}修改的EntityType:ChildRecord}
从EF生成的SQL正确创建了OtherChildObject,但它正在尝试更新不存在的ChildRecord。有人知道发生了什么吗?预先感谢
答案 0 :(得分:2)
从DetectChanges honors store-generated key values开始的重大变化:
旧行为
在EF Core 3.0之前,DetectChanges发现的未跟踪实体将 在添加状态下进行跟踪,并在插入时作为新行插入 将调用SaveChanges。
新行为
从EF Core 3.0开始,如果实体使用生成的键值 并设置了一些键值,则该实体将在 修改状态。这意味着该实体的行被假定为 存在,并且将在调用SaveChanges时进行更新。如果钥匙 值未设置,或者实体类型未使用生成的键, 那么新实体仍将像以前一样被跟踪为已添加 版本。
为什么
进行此更改是为了使其工作更轻松,更一致 在使用商店生成的键时,断开实体图的连接。
缓解措施
如果配置了实体类型,此更改可能会中断应用程序 使用生成的键,但为新的键值显式设置 实例。解决方法是将关键属性显式配置为 不使用生成的值。例如,使用流畅的API:
modelBuilder .Entity<Blog>() .Property(e => e.Id) .ValueGeneratedNever();
或带有数据注释:
[DatabaseGenerated(DatabaseGeneratedOption.None)] public string Id { get; set; }
如果您明确设置了ChildObjects的ID,并且实体使用的是生成的键值,则将在“修改”状态下跟踪它们。