#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. Я снова возвращаюсь к нулевому суду