#c# #entity-framework-4 #poco
#c# #entity-framework-4 #poco
Вопрос:
Об этой ошибке МНОГО спрашивали. Но ни один из случаев, которые, я думаю, не применимы к моему конкретному случаю, или, по крайней мере, не совсем.
Я создаю новую сущность с 2 свойствами навигации, которые являются коллекциями. И объект, и свойства навигации являются новыми объектами, которых нет в базе данных. Моя проблема в том, что всякий раз, когда я пытаюсь присоединить объект к контексту, если в любой из коллекций содержится более 1 элемента, я получаю вышеупомянутое исключение.
Я получаю эту ошибку в Attach()
инструкции в следующем коде:
using (var context = new NSModel())
{
context.Notifications.Attach(e);
context.ObjectStateManager.ChangeObjectState(e,
StateHelpers.GetEquivalentEntityState(e.State));
foreach (NavigationProperty1 np in e.NavigationProperty1s)
context.ObjectStateManager.ChangeObjectState(np,
StateHelpers.GetEquivalentEntityState(np.State));
foreach (NavigationProperty2 np in e.NavigationProperty2s)
context.ObjectStateManager.ChangeObjectState(np,
StateHelpers.GetEquivalentEntityState(np.State));
context.SaveChanges();
return e;
}
Код предназначен для веб-сайта, поэтому объекты не имеют состояния, а контекст создается и удаляется при каждом вызове…
Есть идеи?
Ответ №1:
И объект, и свойства навигации являются новыми объектами, которых нет в базе данных.
Тогда возникает вопрос: почему вы используете Attach
? С помощью Attach
вы сообщаете EF, что объекты находятся в базе данных, и EF будет рассматривать значения свойств первичного ключа как значения столбца PK в базе данных. Поскольку эти свойства должны быть уникальными, EF будет жаловаться, как только у вас будет два объекта с одинаковыми значениями ключа. Вполне возможно, что у вас такая ситуация, когда вы автоматически создаете идентификаторы в качестве свойств ключа и не задаете значения при создании объектов.
Простой пример:
public class Parent
{
public Parent
{
Children = new List<Child>();
}
public int Id { get; set; }
public ICollection<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
}
Этот код …
using (var ctx = new MyContext())
{
var parent = new Parent();
var child1 = new Child(); // <- Id is 0
var child2 = new Child(); // <- Id is 0 as well
parent.Children.Add(child1);
parent.Children.Add(child2);
ctx.Parents.Attach(parent); // <- exception here
//...
}
… выдаст ваше исключение, потому что EF пытается присоединить два разных дочерних экземпляра с одним и тем же ключом 0
. Когда подключается второй дочерний child2
элемент, он говорит: «Объект (а именно child1
) с тем же ключом (а именно 0
) уже существует в ObjectStateManager».
Если вы хотите добавить весь граф объектов в качестве новых объектов в базу данных, вы можете просто вызвать context.Notifications.AddObject(e);
вместо Attach
.
Комментарии:
1. Спасибо… На самом деле я заставил его работать с помощью attach(), но ваши решения более чистые и элегантные.