Это мой первый пост здесь, поэтому я надеюсь, что все в порядке.Проблема с таблицами EF STE и Self-Referencing
вот моя проблема: У меня есть таблица в моей базе данных под названием UserTypes. Он имеет:
- ID;
- IsPrivate;
- Parent_ID;
Соответствующие являются первыми и третьими. У меня есть другая таблица под названием UserTypes_T, которая имеет информацию для разных типов, которая зависит от языка. Поля следующие:
- Language_ID;
- UserType_ID;
- Наименование;
То, что я пытаюсь достичь загрузить всю иерархию из UserTypes таблицы и показать его в TreeView (это не относится в настоящее время). Затем, выбрав некоторые типы пользователей, я могу редактировать их в отдельном окне редактирования (имя) и поле со списком (родительский).
Все работает нормально, пока не попытаюсь сохранить изменения в базе данных. EF сгенерировал для меня два класса объектов для этих таблиц:
Класс для пользовательских типов имеет:
- ID;
- IsPrivate;
- Parent_ID;
- Навигационное свойство для саморекламы (0..1);
- Навигационное свойство для дочерних элементов;
- Другое навигационное свойство для таблицы UserTypes_T (1 .. *);
Класс для преобразованной информации:
- UserType_ID;
- Language_ID;
- Наименование;
- Навигационное свойство таблицы UserTypes (* .. 1);
- Навигационное свойство таблицы языков (* .. 1);
Я получаю данные мне нужно, используя:
return context.UserTypes.Include("UserTypes_T").Where(ut => ut.IsPrivate==false).ToList();
в моем WCF веб-службы. Я могу добавлять новые типы пользователей без проблем, но когда я пытаюсь обновить старые, происходят некоторые странные вещи.
Если я обновляю корневой элемент (Parent_ID == null), все работает! Если я обновить элемент, где PARENT_ID = NULL я получаю следующее сообщение об ошибке:
AcceptChanges cannot continue because the object’s key values conflict with another object in the ObjectStateManager.
я искал по всему интернету и читать записи в блоге от Diego B Vega (и многое другое), но моя проблема отличается. Когда я изменяю тип родительского пользователя, я фактически изменяю свойство Parent_ID, а не навигационное свойство. Я всегда стараюсь работать с идентификаторами, а не с созданными навигационными свойствами, чтобы избежать проблем.
Я сделал небольшое исследование, пытались увидеть, что объект график, который я и увидел, что там было много дублирующих организаций:
Корневой элемент был список его дочерних элементов. Каждый дочерний элемент имел обратную ссылку на корень или его родительский элемент и так далее. Ты можешь представить. Поскольку я не использовал эти навигационные свойства, потому что я использовал идентификаторы для получения/установки необходимых мне данных, я удалил их из модели. Конкретно я удалил пункты и из UserTypes класс сущности. Тогда у меня был граф объектов с каждым элементом только один раз. Я попробовал новое обновление, но у меня была такая же проблема:
Корневой элемент был обновлен отлично, но у элементов, у которых были родители, было исключение.
Я видел, что у меня было навигационное свойство в классе сущностей UserTypes_T, указывающее на тип пользователя, поэтому я тоже удалил его. Затем эта ошибка исчезла. Все элементы в графе объектов были уникальными. Но проблема осталась - я мог бы обновить свой корневой элемент без проблем, но при попытке обновления детей (без исключений) я получил нулевое ссылочное исключение в созданном классе Model.Context.Extensions:
if (!context.ObjectStateManager.TryGetObjectStateEntry(entityInSet.Item2, out entry))
{
context.AddObject(entityInSet.Item1, entityInSet.Item2);//here!
}
Я попытался обновить только имя (которое находится в UserTypes_T), но ошибка совпадает.
У меня нет идей, и я пытался решить эту проблему в течение 8 часов, поэтому я буду признателен, если кто-то даст мне идеи или поделится своим опытом.
PS:
Единственный способ мне удалось обновить дочерний объект использует следующий код для извлечения данных:
var userTypes = argoContext.UserTypes.Include("UserTypes_T").Where(ut => ut.IsPrivate==false).ToList();
foreach (UserType ut in userTypes)
{
ut.UserType1 = null;
ut.UserTypes1 = null;
}
return userTypes;
где UserType1 является навигационным свойством, указывая на родительском пользователя type и UserTypes1 - это навигационное свойство, содержащее список дочернего элемента. Проблема здесь заключалась в том, что EF «фиксирует» объекты и изменяет Parent_ID на null. Если я верну его снова, EF также установит UserTypes1 ... Может быть, есть способ остановить это поведение?