有时实体框架在将“子”添加到新(父)元素后插入多个“父”行

Posted

技术标签:

【中文标题】有时实体框架在将“子”添加到新(父)元素后插入多个“父”行【英文标题】:Sometimes entity framework inserts multiple "parent" row after adding "children" to a new (parent) element 【发布时间】:2019-10-17 06:32:32 【问题描述】:

我正在尝试找出在向实体添加子对象的情况下可能导致实体相乘的原因(一对多连接)。

我的代码很复杂,类有更多的属性,但主要问题如下。

这是一个示例代码:

public class Parent

    public int Id  get; set; 
    public List<Child> Children  get; set; 
    public string Name  get; set; 
    public Parent()
    
        Children = new List<Child>();
    


public class Child

    public int Id  get; set; 
    public Parent Parent  get; set; 
    public int ParentId  get; set; 
    public string ParentName  get; set; 

孩子可以在没有父母的情况下生活

所以当我想连接两个实体时,它必须在代码中正常工作。如果已有父实体,则无法创建新的父实体。 过程是线性的。

例如,我首先创建了 三个孩子,没有父母(这是第一个状态),然后将其保存到 Db。 然后我“处理”实体(可能在创建孩子后的一天):

选择第一个子项并在无法通过其名称找到父项时创建父项(子项已在数据库中)。

child 添加到父级的非子级列表中。

保存 dbContext。

当我有没有父母的孩子时循环。

代码示例:

public void ProcessChildren()

    IDbContextTransaction trans = dbContext.BeginTransaction();
    foreach(var item in Children) //Children is a list of child entities (existing in the DB)
    
        var parent = dbContext.Parents.SingleOrDefault(x => x.Name == item.ParentName);
        if(parent == null)
        
            parent = new ParentName = item.ParentName;
            dbContext.Parents.Add(parent);
        
        parent.Children.Add(item);
        dbContext.SaveChanges();
    
    trans.Commit(); //rollback implemented if it fails

那时我所拥有的(只是有时而且很少)是3个父母和3个孩子女巫没有ParentIds,所以看起来(对我来说)EF以某种方式崩溃了并且不小心这样做了。

所以这个错误发生在一个巨大的过程中(从几十万个孩子创造了几万个父母)并且这个错误出现的机会仍然非常低(不是真的有意重现)。但是在我的系统中它会导致后果。

有人听说过这样的行为吗?也许问题出在它的 EF(EntityFramework 6.2.0 Nuget)或 Npgsql 扩展(EntityFramework6.Npgsql 3.1.1 Nuget)上?

编辑:添加保存和创建实体的代码示例。 Edit2: 父空引用异常修复。 抱歉,此处编写的代码只是其工作方式的示例,而不是代码本身。

【问题讨论】:

您需要将新创建的父级分配给子记录的位置添加(以最小的方式) @TheGeneral 添加了一个我想到的例子。 【参考方案1】:

在这一行之后,您只需在数据库上下文中添加新的父级,但您的“父级”变量不会更改,它将保持为空。

if(parent == null)

    dbContext.Parents.Add(new ParentName = item.ParentName);

所以每次 parent 为 null 时,当你想访问这里的 null 变量parent.Children.Add(item);时,你的代码就会崩溃@

您可以尝试将父变量分配给新添加的父对象。

if (parent == null)

    parent = dbContext.Parents.Add(new ParentName = item.ParentName);

【讨论】:

是的,你说得对,谢谢。我在这里更正了。这不可能是“真实代码”中的问题原因,它是以正确的方式创建的。其他方式我会得到 NullReferenceException 并且整个过程将回滚。

以上是关于有时实体框架在将“子”添加到新(父)元素后插入多个“父”行的主要内容,如果未能解决你的问题,请参考以下文章

Linq-To-Sql 尝试插入父实体而不是子实体

实体框架 6:将子对象添加到父列表与将子对象的导航属性设置为父对象

最有效的实体框架代码第一方法展平/投影具有特定子实体的父实体

使用实体框架插入时设置 Id 字段

实体框架 - 连接新添加的 Poco 实体并加载子对象(插入/添加)

vue 高阶组件必备知识$attrs,inheritAttrs,$listenters详解