EF6 Добавить объект в коллекцию, используя только его идентификатор - PullRequest
0 голосов
/ 23 сентября 2019

У меня есть проблема, мне нужно добавить объект в коллекцию с чтением из EF.Поскольку объект, которому принадлежит коллекция, позднее будет добавлен в другой контекст.

Пример события объекта создается и сохраняется в EFContext 1 и получает идентификатор 1. События необходимо сохранить здесь, а затем добавить в коллекцию.

Entity Car создан, но не добавлен и не сохранен в контексте.Автомобиль передается между несколькими функциями и после того, как пользователь нажимает кнопку.Автомобиль передается другому классу и там добавляется второй DBContext (2).Или, возможно, пользователь отменяет и автомобиль не сохраняется, и Событие живет так, как доказывает это.

Автомобиль имеет коллекцию событий как собственность.Я хочу добавить событие в эту коллекцию, но только с использованием его идентификатора, потому что автомобиль позже добавляется и сохраняется другим DBContext 2.

Обычно я хочу загрузить событие из текущего DBContext и добавить его в машину.организация.Но тогда два DBContexts смешиваются.Мне нужно что-то вроде Car.Events.Add(new Event() {EventId == 1}); Но для этого нужно создать новое событие, а не то, что я хочу.

Я не могу получить доступ к таблице отношений (через EF), потому что генерируется EF.

Возможно ли то, что я хочу?

1 Ответ

2 голосов
/ 24 сентября 2019

Существуют варианты, которые могут подходить для вашего сценария, но я бы посоветовал соблюдать осторожность при работе с ограниченным контекстом, не принимая во внимание стоимость загрузки сущностей в каждом контексте, который на них ссылается.В случае, когда один DbContext создал событие, а другой DbContext создает автомобиль, который вы хотите привязать к этому существующему событию, зная этот идентификатор события, вы можете сделать что-то вроде этого:

using (var carContext = new CarContext())
{
   var event = new Event { Id = eventId };
   carContext.Events.Attach(event);
   var car = new Car { /* ... */ };
   car.Events.Add(event);

   carContext.SaveChanges();
}

Есливторой контекст является более долгоживущим, таким как область действия для веб-запроса и т. д., затем вам следует сначала выполнить поиск события в контексте, используя эту ссылку, прежде чем прикреплять событие.

Event event = carContext.Events.Local.SingleOrDefault(x => x.Id == eventId);
if (event == null)
{
   event = new Event { Id = eventId };
   carContext.Events.Attach(event);
}
// ...

Это вызовет исключенияв SaveChanges, если это событие не было сохранено или с тех пор было удалено до вызова этого кода.

Обычно, если я ограничил контексты, где контекст Car должен знать о событиях, но заботится только о чтении / связыванииих для автомобилей, и мне нужна только пара столбцов, я сопоставляю упрощенную модель сущностей событий с событиями, содержащими только те поля, которые мне нужны, и тогда я могу недорого загрузить их в контексте.Если, например, в таблице «Событие» было 30 столбцов, но что касается автомобилей, то мне просто нужны были идентификатор события, имя и DateTime события, мой CarContext отображал бы облегченную сущность события только с этими 3 столбцами, а не полное определение сущности события.Таким образом, мой автомобильный контекст может безопасно и дешево загрузить и связать это событие:

using (var carContext = new CarContext())
{
   var event = carContext.Single(x => x.Id == eventId); // Selects 3 columns from DB or can load from cache for longer-lived contexts. I get an exception here if the Event doesn't exist rather than SaveChanges.
   var car = new Car { /* ... */ };
   car.Events.Add(event);

   carContext.SaveChanges();
}

Предостережение заключается в том, что это легковесное событие не может быть использовано для создания строк события, если оно не имеет всех полей, не допускающих нулевое значение, идаже тогда только один DbContext должен нести ответственность за вставку любого нетривиального объекта.Я обычно добавляю к имени этих объектов префикс "Lw" для Lightweight, т.е. "LwEvent".Эти объекты имеют заголовок комментария, указывающий, что они не предназначены для вставки.

...