EF AddOrUpdate Seed does not Update Child Entities

2019-04-04 08:58发布

问题:

I'm having some issues Seeding data and I was able to reproduce the issue with a very small application.
Given you have this Seed Method:

    protected override void Seed(JunkContext context)
    {
        context.Junks.AddOrUpdate(x => x.Name,
            new Junk()
            {
                Name = "BANANAS!!",
                Item = new JunkItem()
                {
                    Name = "APPLES!!!"
                }
            }
        );
    }

when you run update-database in the PMC all of the entities get created successfully. Good.
But when you wish to go and update the database, say your seed method is now this:

    protected override void Seed(JunkContext context)
    {
        context.Junks.AddOrUpdate(x => x.Name,
            new Junk()
            {
                Name = "BANANAS!!",
                Item = new JunkItem()
                {
                    Name = "ORANGES!!!"
                }
            }
        );
    }

The child entity is not updated. It seems the only way we can re-seed is to wipe the database and reseed everything. I think I understand as to why this does not work the way I expect it to, but perhaps someone could point me in the right direction to update this seed method accordingly. I know I could just write out context.JunkItems. (...) but that seems like it would beat the whole purpose of 'AddOrUpdate'.

I think I would have to define 'keys' for each child entity. Example: 'Junk' gets x => x.Name but 'JunkItem' currently has to 'update key' set. I'm assuming that's the issue, but how would I go about handling that?

回答1:

No command in EF automatically updates child - AddOrUpdate is no difference, it internally check existence of the top level entity (Junk in your case) and insert or update it if it doesn't exist. The insertion of children is a side effect in this case because when AddOrUpdate internally calls Add it adds whole object tree. AddOrUpdate does really much less magic than people expect but even with this small amount of magic it should be used only in migration seeding because it is quite expensive operation (additional roundtrip to database for every entity and a lot of reflection).

Child must always be updated separately - it may require your own separate queries to database to find correct child and common EF update.