Семя EF AddOrUpdate не обновляет дочерние сущности

У меня возникли некоторые проблемы с заполнением данных, и я смог воспроизвести проблему с очень маленьким приложением.
Учитывая, что у вас есть этот метод заполнения:

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

когда вы запускаете базу данных обновления в PMC, все объекты успешно создаются. Хорошо.
Но когда вы захотите обновить базу данных, скажите, что ваш начальный метод теперь таков:

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

Дочерняя сущность не обновляется. Кажется, единственный способ, которым мы можем повторно заполнить, — это стереть базу данных и повторно заполнить все. Я думаю, что понимаю, почему это не работает так, как я ожидаю, но, возможно, кто-то может указать мне правильное направление, чтобы соответствующим образом обновить этот начальный метод. Я знаю, что могу просто написать context.JunkItems. (...) но похоже, что это превзошло бы всю цель «AddOrUpdate».

Я думаю, мне придется определить «ключи» для каждого дочернего объекта. Пример: «Нежелательная почта» получает x => x.Name, но «JunkItem» в настоящее время должен установить «обновить ключ». Я предполагаю, что проблема в этом, но как мне с этим справиться?


person Peanut    schedule 13.08.2012    source источник


Ответы (1)


Никакая команда в EF автоматически не обновляет дочерний элемент - AddOrUpdate не имеет значения, она внутренне проверяет наличие объекта верхнего уровня (Junk в вашем случае) и вставляет или обновляет его, если он не существует. Вставка дочерних элементов в этом случае является побочным эффектом, потому что когда AddOrUpdate вызывает Add, он добавляет целое дерево объектов. AddOrUpdate на самом деле делает гораздо меньше магии, чем ожидают люди, но даже с таким небольшим количеством магии ее следует использовать только при заполнении миграции, потому что это довольно дорогая операция (дополнительный обмен данными с базой данных для каждой сущности и много размышлений).

Дочерний элемент всегда должен обновляться отдельно — для поиска правильного дочернего и общего обновления EF могут потребоваться ваши собственные отдельные запросы к базе данных.

person Ladislav Mrnka    schedule 14.08.2012
comment
Спасибо за отзыв. Я просто пытаюсь избежать создания новой переменной для всех этих детей. Я создал метод расширения под названием «AddOrUpdateChild», который просто вызывает «AddOrUpdate», а затем возвращает переданный ему экземпляр T. Таким образом, вы можете «AddOrUpdate» свой дочерний экземпляр вручную и установить все внешние ключи в строке. До сих пор, во время первоначальных испытаний, это оказалось успешным. - person Peanut; 14.08.2012
comment
когда вы вызываете AddOrUpdate, то как вы возвращаете экземпляр T? Возвращает ли он идентификатор вставленного элемента? можешь поделиться? - person Learner; 09.06.2015
comment
На самом деле вам вообще не нужно возвращать экземпляр T при добавлении или обновлении. EF очень ООП, и контекст обеспечивает ссылочную целостность. Это означает, что если вы добавляете или обновляете объект, которому будет назначен FK или PK после операции, объект, который вы удерживаете в памяти, будет автоматически обновлен, чтобы иметь эти назначенные свойства. Попробуйте сами: поместите сгенерированный базой данных PK на модель, а затем вставьте модель через EF. Затем без повторного запроса к БД проверить ПК на модели. Его следует обновить, чтобы показать новый назначенный ПК. - person Kris Coleman; 15.02.2018