EF Core 2.0 When property is calculated based on list of entities it requires two SaveChanges()

c# entity-framework entity-framework-core

Question

Parent has a property LastChildrenName and a list of the childrens.

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();

During debugging before first call of SaveChanges() the LastChildrenName has a proper value of ThirdChild however after SaveChanges() only new Children row appears in the db and the LastChildrenName column has value SecondChild.

Calling again SaveChanges() right after, in the next line of code causes that parent's column LastChildrenName is updated with proper value.

But it also causes rising the update trigger twice on the Parent table which I want to avoid.

Am I missing an EF Core setting or a way which can be used on Parent model to update in the db only once? I would like also to avoid changing the get method of LastChildrenName property.

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));
}

Children model:

public class Children 
{
    public int Id;
    public string Name;
    public Parent Parent;
}
1
0
4/19/2018 11:45:21 AM

Accepted Answer

OrderBy(x => x.Id) orders children by ID, but before the children are saved to the database, they don't have a known ID yet. Therefore, to take the simple case first, if FirstChild and SecondChild are already saved with IDs 1 and 2, and your ThirdChild is added to the context but not saved yet, that third child will be seen as having ID 0, so it would make sense that SecondChild is still seen as having the highest ID.

If you only ever add one child at a time, you can modify your OrderBy so that 0 will always appear last. You can, for instance, write OrderBy(x => x.Id == 0).ThenBy(x => x).

If you add multiple children at the same time, I don't think this is going to work at all, because there is no guarantee that entities will be saved to the database in any particular order. You'd need to switch to generating IDs on the client rather than on the server to let that approach work. Alternatively, you might add a creation date/time and order by that instead.

2
4/19/2018 12:40:58 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow