Entity Framework хранит объекты-призраки?

#c# #entity-framework #entity

#c# #entity-framework #сущность

Вопрос:

Давайте сделаем это проще… Предположим, у меня есть 2 объекта:

 Приложение
 Идентификатор: int (первичный ключ, автоинкремент)
 Имя: строка(60)
 Клиент: пользователь
 Разработчик поддержки: пользователь

 Пользователь
 Идентификатор: int (первичный ключ, автоинкремент)
 Имя: строка(60)
 Адрес электронной почты: строка (60)

Предположим также, что у меня есть метод с именем Create, который получает экземпляр приложения, созданный (на другом уровне) без участия контекста:

 var application = новое приложение
 {
 Name = "Visual Studio 2010", 
 Клиент = новый пользователь { Id = 12}, 
 SupportEngineer = новый пользователь { Id = 14}
 };

Обратите внимание, что пользователь с идентификаторами == 12 и == 14 существует в базе данных!!

 создать общедоступную пустоту (приложение application) {
 приложение.Клиент = контекст.Пользователи.FirstOrDefault(e => e.Id == приложение.Client.Id );
 приложение.Поддерживающий инженер = Контекст.Пользователи.FirstOrDefault(e => e.Id == приложение.Поддержка инженера.Идентификатор);
 Контекст.Приложения.AddObject (приложение);
 Context.SaveChanges(); 
 }

Когда я проверяю объекты в контексте перед вызовом SaveChanges, я получаю пользовательские объекты, созданные перед вызовом метода Create, как «добавленные».

Почему это происходит, если я переопределяю значения клиента properties и SupportEngineer объектами из базы данных? Почему созданные вручную объекты ( new User { Id = 12 }, new User { Id = 14 } ) все еще существуют, более того, в контексте с состоянием «добавлено»?

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

1. В чем здесь реальная проблема? Является ли состояние Application недопустимым после вызова Create?

2. Реальная проблема заключается в том, что EF попытается создать / вставить двух новых пользователей, что не является желаемым поведением

3. Какие состояния вы видите перед вызовом AddObject ?

4. объекты, созданные вне контекста, сохраняются в добавленном состоянии

Ответ №1:

Просто сделайте это:

 var application = new Application
   {
      Name = "Visual Studio 2010",
      ClientId = 12,
      SupportEngineerId = 14
   };
  

И пусть метод Create просто создаст объект:

 public void Create(Application application) {
    Context.Applications.AddObject(application);
    Context.SaveChanges();
}
  

Не прямой ответ, но некоторые общие рекомендации:

Еще одна вещь, на которую вы, возможно, захотите обратить внимание, это выглядит так, как будто вы повторно используете свой DbContext. Как правило, это плохая идея, особенно при добавлении / удалении объектов. Например, после удаления удаленные объекты все еще известны по контексту. Вместо этого я бы рекомендовал шаблон типа:

 using(var ctx = new MyContext())
{
    ctx.Applications.Add(application);
    ctx.SaveChanges();
}
  

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

1. У меня нет этих свойств (ClientID, SupportEngineerId), поскольку моя модель была сгенерирована без включения внешних ключей в качестве части модели.

2. Несмотря на то, что такое поведение происходит с кодом, сгенерированным из коробки, я использовал POCOs, сгенерированный плагином «ADO.NET Генератор сущностей POCO» и установка ctx.ContextOptions. ProxyCreationEnabled = false решил проблему, с которой я столкнулся

3. ctx.ContextOptions. ProxyCreationEnabled = false создает другие проблемы, которых у меня не было в первую очередь.

4. Я снова возвращаюсь к нулевому суду