EF Core 2.0当根据实体列表计算属性时,它需要两个SaveChanges()

时间:2018-04-19 11:35:01

标签: c# entity-framework entity-framework-core

父母有一个属性LastChildrenName和一个孩子的列表。

parent.Children.Add(new Children(){ Name = "FirstChild" };
parent.Children.Add(new Children(){ Name = "SecondChild" };
parent.Children.Add(new Children(){ Name = "ThirdChild" };

DbContext.Set<Parent>.Update(parent);
DbContext.SaveChanges();
DbContext.SaveChanges();

在第一次调用SaveChanges()之前的调试期间,LastChildrenName具有正确的值ThirdChild但是在SaveChanges()之后,只有新的Children行出现在数据库和LastChildrenName中列的值为SecondChild

在下一行代码之后再次调用SaveChanges()会导致父列的LastChildrenName列更新为适当的值。

但它也会导致父表上的更新触发器上升两次,我想避免。

我是否缺少EF Core设置或可以在父模型上使用的方式仅在数据库中更新一次? 我还想避免更改LastChildrenName属性的get方法。

public class Parent
{
    public int Id;
    public ICollection<Children> Childrens {get;set;}

    public string LastChildrenName => this.Childrens.OrderBy(x => x.Id).Select(x => x.Name).LastOrDefault(x => !string.IsNullOrWhiteSpace(x));
}

儿童模特:

public class Children 
{
    public int Id;
    public string Name;
    public Parent Parent;
}

1 个答案:

答案 0 :(得分:2)

OrderBy(x => x.Id)按ID对子项进行排序,但在将子项保存到数据库之前,它们还没有已知的ID。因此,要首先采用简单案例,如果FirstChildSecondChild已使用ID 12保存,并且您的ThirdChild已添加到上下文中但尚未保存,第三个孩子将被视为ID 0,因此SecondChild仍然被视为拥有最高ID。

如果您一次只添加一个孩子,则可以修改OrderBy,以便0始终显示在最后。例如,您可以编写OrderBy(x => x.Id == 0).ThenBy(x => x)

如果您同时添加多个子节点,我认为这根本不起作用,因为无法保证实体将以任何特定顺序保存到数据库中。您需要切换到在客户端而不是服务器上生成ID以使该方法有效。或者,您可以添加创建日期/时间和顺序。