#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 заботится об этих «множественных» добавлениях. Т.е. повторное добавление объектов, которые уже были добавлены через ссылки, не вызовет исключений или множественных объектов в базе данных.