Отслеживание внешних ключей Entity framework вызывает проблему

#c# #.net #entity-framework

#c# #.net #entity-framework

Вопрос:

работа с EF4, первый подход модели в версии 2010:

Рассмотрим следующую EntityModel:

«OrderBase» — это абстрактная сущность только с одним свойством «Name»

«Detail» (с одним свойством «Text») — это объект, который имеет связь «многие к одному» с «OrderBase» (т. е. одна база заказов имеет несколько деталей)

«Комментарий» (с одним свойством «Text») — это объект, который имеет связь «многие к одному» с «OrderBase» (т. е. одна база заказов имеет несколько комментариев)

«MusicOrder» — это объект, производный от «OrderBase», имеющий только одно свойство «Количество» (int)

«SongOrder» — это объект, производный от «OrderBase», имеющий только одно свойство «Length» (int). Порядок песен имеет отношение «многие к одному» к MusicOrder (т. е. один MusicOrder имеет несколько SonOrders)

Для краткого обзора: Хотел опубликовать изображение datamdel, но мне не разрешено… Итак, любые вопросы, касающиеся модели данных.

Итак, теперь я создаю свою базу данных, выполняю ddl-скрипт и пытаюсь запустить следующий код:

 using (DataContainer container = new DataContainer())
{
    MusicOrder musicOrder = new MusicOrder{Name = "Oldies", Quantity = 1};
    SongOrder songOrder = new SongOrder {Name = "Great balls of fire", Length = 240};
    songOrder.Details.Add(new Detail{Text = "Song from Jerry Lee Lewis"});
    songOrder.Comments.Add(new Comment{Text = "Cool song"});

    container.OrderBaseSet.AddObject(songOrder); //relevant line
    musicOrder.SongOrders.Add(songOrder);

    songOrder.Details.Clear();
    songOrder.Comments.Clear();
    container.OrderBaseSet.AddObject(musicOrder);
    container.SaveChanges();
}
  

В этом случае «SaveChanges» приводит к исключению, сообщающему мне что-то об отсутствующих связях внешнего ключа…

Но если я перемещу строку

 container.OrderBaseSet.AddObject(songOrder);
  

после «Очистить»-часть, приводящая к следующему коду:

 using (DataContainer container = new DataContainer())
{
    MusicOrder musicOrder = new MusicOrder{Name = "Oldies", Quantity = 1};
    SongOrder songOrder = new SongOrder {Name = "Great balls of fire", Length = 240};
    songOrder.Details.Add(new Detail{Text = "Song from Jerry Lee Lewis"});
    songOrder.Comments.Add(new Comment{Text = "Cool song"});

    musicOrder.SongOrders.Add(songOrder);

    songOrder.Details.Clear();
    songOrder.Comments.Clear();

    container.OrderBaseSet.AddObject(songOrder); //relevant line
    container.OrderBaseSet.AddObject(musicOrder);
    container.SaveChanges();
}
  

все работает нормально.

Как вы можете видеть, я знаю, как обойти исключение, и я знаю, что нет смысла «дважды добавлять» порядок песен. Но мне интересно, является ли это ошибкой или особенностью. Почему в моем первом примере генерируется исключение. Был бы очень признателен за исчерпывающее объяснение. На мой взгляд, entity framework также должна иметь возможность обрабатывать первый пример и не выдавать исключение. Поэтому я бы сказал, что это ошибка.

Не стесняйтесь комментировать 😉

Andi

Ответ №1:

Это происходит потому, что вызов AddObject добавляет не только один объект, но и все связанные объекты, которые также не привязаны к контексту. Итак, при вызове AddObject(songOrder) в первом примере вы также добавляете Detail и Comment . Но после этого вы вызываете Remove свойства навигации, чтобы удалить оба Detial и Comment . Remove на подключенных объектах только разорвется связь, но это не приведет к удалению Detail и Comment из контекста (это только установит их основное отношение на null), поэтому, как только вы попытаетесь вызвать SaveChanges , он взорвется, потому что вы пытаетесь сохранить Detail и Comment без связанных OrderBase (я предполагаю, что отношения не являются нулевыми).

Во втором примере Comment и Detail удаляется перед добавлением порядка в контекст, поэтому он ведет себя так, как ожидалось.

Это не ошибка, это «особенность».

Комментарии:

1. Спасибо за ответ. Я не вижу здесь «функции». Если entity Framework достаточно «интеллектуальна», чтобы в первую очередь добавлять детали и комментарии, и я ничего не отправлял в базу данных, она также должна быть достаточно интеллектуальной, чтобы удалить все эти объекты из контекста. Итак, подведем итог: контекст сущности всегда ведет себя так, как будто все мгновенно передается в базу данных. Поэтому я должен рассматривать это как хранилище базы данных, а не как контекст объекта.

Ответ №2:

вам не нужно добавлять порядок песен в базу. просто добавьте песню в музыку, а затем музыку в базу.

Скорее всего, вам не нравится, что вы добавляете песню, которая не связана с музыкой.

Комментарии:

1. Привет, спасибо за ваш ответ. Entity Framework заботится об этих «множественных» добавлениях. Т.е. повторное добавление объектов, которые уже были добавлены через ссылки, не вызовет исключений или множественных объектов в базе данных.