Entity Framework - Вставка родительской и дочерней модели одновременно с FK - PullRequest
0 голосов
/ 02 октября 2018

У меня есть приложение ASP.NET MVC, использующее Entity Framework.Я разработал 2 модели, используя подход базы данных (код) для базы данных SQL Server 2008 R2.Одна модель по сути является родительской моделью, а другая - дочерней моделью, которая содержит внешний ключ для столбца, сгенерированного базой данных родительской модели.

Псевдокод:

CREATE TABLE PARENT
(
    ROWID BIGINT IDENTITY(1,1) NOT NULL,
    VALUE NVARCHAR(255) NOT NULL,

    PRIMARY KEY(ROWID)
);

CREATE TABLE CHILD
(
    ROWID BIGINT IDENTITY(1,1) NOT NULL,
    PARENT_ROWID BIGINT NOT NULL,
    VALUE NVARCHAR(255) NOT NULL,

    PRIMARY KEY(ROWID),
    FOREIGN KEY(PARENT_ROWID) REFERENCES PARENT(ROWID)
);

Всеэто работает нормально, и я могу связать свои данные с моей моделью и редактировать поля и так далее.У меня вопрос: если я пытаюсь создать записи для этих моделей, как я могу это сделать, когда внешний ключ для CHILD находится в PARENT, который еще не доступен, если я создаю их одновременно?

Итак, мои текущие основные шаги:

  1. Получить список PARENT моделей для вставки в базу данных
  2. Вставка PARENT моделей
  3. Звоните SaveChanges()

    • Для каждого РОДИТЕЛЯ:

      1. Получить FK для РОДИТЕЛЯ
      2. Получить список моделей ДЕТЯМ для вставкив базу данных
      3. Для каждой модели РЕБЕНКА вставьте РЕБЕНКА с этим FK
      4. Вызов SaveChanges()
  4. Дополнительные операции и обновления базы данных для других моделей

  5. Вызов SaveChanges()

Я уверен, что мог бы оптимизировать это, но это не то, что меня беспокоит.Мне кажется, что должен быть какой-то способ сделать это без ручного поиска FK или ручной настройки FK.Если мне нужно, я могу сделать это, но я бы хотел использовать только один вызов SaveChanges() для передачи этих команд в одной транзакции.Я ищу что-то вроде:

  1. Получить список моделей PARENT для вставки в базу данных

    • Для каждого РОДИТЕЛЯ
      1. Вставить PARENT и вернуть новый FK (без сохранения)
      2. Получить список моделей CHILD для вставки в базу данных
      3. Для каждой модели CHILD вставить CHILD с этим FK
  2. Дополнительные операции и обновления базы данных для других моделей

  3. Вызов SaveChanges()

КомуЕсли предоставить некоторый контекст, в моей фактической таблице есть много столбцов, которые не гарантированно являются уникальными (именно поэтому PK имеет ROWID), и каждая из этих строк имеет отношения «нет ко многим» с дочерней таблицей, где дочерняя таблица такжеможет иметь неуникальные строки.Не очень идеально, но это то, чего требуют наши операции сейчас.Я включил здесь псевдокод, потому что реальный код проприетарный, но я мог бы создать реальный макет, если это необходимо.

Есть предложения?

Спасибо

РЕДАКТИРОВАТЬ: Поэтому я изменил свой код, чтобы использовать свойство навигации, как предложено.Это почти работает.Вот мой код:

List<PARENT> parents = getParents();
List<CHILD> children = getChildren();
foreach (PARENT parent in parents)
{
    db.PARENT.add(parent);
    foreach (CHILD child in children)
    {
        child.PARENT = parent;
        db.CHILD.add(child);
    }
}

db.SaveChanges();

На первый взгляд, это именно то, что я искал.Однако, когда я запускаю его, дочерние записи вставляются только для первой родительской записи.Так, например, если у меня есть 3 записи PARENT и 3 записи CHILD, у меня должно быть 9 новых записей в моей таблице CHILD.Однако после этого кода у меня есть только 3 записи для первого РОДИТЕЛЯ.

Я предполагаю, что это как-то связано с тем, что я неоднократно использую один и тот же список детей, и Entity Framework просматривает их как дубликаты.Я переместил его в цикл PARENT for следующим образом, и он работает как положено:

List<PARENT> parents = getParents();
foreach (PARENT parent in parents)
{
    db.PARENT.add(parent);
    List<CHILD> children = getChildren();
    foreach (CHILD child in children)
    {
        child.PARENT = parent;
        db.CHILD.add(child);
    }
}

db.SaveChanges();

Но я бы предпочел этого не делать, поскольку функция getChildren () довольно громоздка.Есть мысли?

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

Я использовал приведенный ниже код для заполнения начальных значений в дБ для таблицы стран с городами, районами, районами и их переводами в рамках одного вызова в дБ.

вы можете реализовать аналогичную структуру для создания родителя -> ребенка ->внуковые сущности в одном и том же вызове дБ;

            var country = new MyCountry {
                Title ="Syria",
                ShortName="SYR",
                 Translations=new[]
                 {
                     new CountryTranslate { LCID=1, Name="سوريا" },
                     new CountryTranslate { LCID=31, Name="Suriye" },
                     new CountryTranslate {LCID=9, Name="Syria" }
                 },
                  Cities=new[]
                  {
                      new MyCity
                      {
                          Title="Lattakia",
                          ShortName = "LAT",
                          Translations=new[]
                          {
                              new CityTranslate { LCID=1, Name="اللاذقية" },
                              new CityTranslate {LCID=31, Name="Lazkiye" },
                              new CityTranslate {LCID=9, Name="Lattakia" }
                          },
                          Districts=new[]
                          {
                              new MyDistrict
                              {
                                  Title="Owineh",
                                  Translations=new[]
                                  {
                                      new DistrictTranslate { LCID=1, Name="العوينة" },
                                      new DistrictTranslate { LCID=31, Name="Uveyne" },
                                      new DistrictTranslate {LCID=9, Name="Owineh" }
                                  },
                                  Neighborhoods = new[]
                                  {
                                      new MyNeighborhood
                                      {
                                          Title="Reji",
                                          Translations = new[]
                                          {
                                              new NeighborhoodTranslate { LCID=1, Name="الريجي"},
                                              new NeighborhoodTranslate { LCID=31, Name="Eski Reji"},
                                              new NeighborhoodTranslate { LCID=9, Name="Old Reji"}
                                          }
                                      }
                                  }
                              }
                          }
                      }
                  }
            }

context.SaveChanges();
0 голосов
/ 02 октября 2018

Использовать свойство навигации;установите свойство nav 'Child.Parent' для еще не сохраненного объекта 'Parent', и EF вставит их в правильном порядке с помощью одного вызова SaveChanges

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...