Ответ 1
FYI, я написал сообщение в блоге с некоторыми дополнительными предложениями о том, что я уже ответил на форумах EF. Здесь - это сообщение в блоге.
Я застрял в этой проблеме уже более недели. Надеюсь, кто-то может указать мне в правильном направлении.
Начну с краткого описания моей схемы.
Активы 1 --- > 1 Адрес * → 1 Район * → 1 Регион * → 1 Страна
Пакет 1 → * Активы
Использование объекта самоконтроля (STE) + WCF.
Шаги:
На шаге 2 вызов использует активную загрузку Адресов.
from p in context.Assets.Include("Address.Area.Region.Country")
Это ошибка при попытке вызвать
context.Packages.ApplyChanges(package)
AcceptChanges не может продолжаться, потому что значения ключа объекта конфликтуют с другой объект в ObjectStateManager. Убедитесь, что значения ключа уникальны перед вызовом AcceptChanges.
ИЗМЕНИТЬ
После snooping вокруг, я обнаружил, что это проблема STE. Проблема заключается в том, что вы не можете сохранять граф, содержащий несколько экземпляров одного и того же объекта, как описано здесь. Вот мой вопрос.
Как добавить объект в свою сущность коллекция. Новый объект может иметь связанные объекты, которые содержат одинаковые ключ как один уже в коллекции. То есть Добавить новый актив, который может содержать тот же адрес, область, регион или страна.
Вот мои ограничения:
Я знаю о возможных решениях, предложенных Diego B Vega, но это не опции, которые я могу использовать для своего решения. У кого-нибудь есть другие идеи?
FYI, я написал сообщение в блоге с некоторыми дополнительными предложениями о том, что я уже ответил на форумах EF. Здесь - это сообщение в блоге.
Вы считали, что просто отказываетесь от ORM и возвращаетесь к нормальному доступу, если знаете, что я имею в виду: -)
Не шутите - к тому моменту, когда вы сражаетесь с одной проблемой, подобной той, которая больше пахнет ошибкой ORM, вы могли бы выпустить свои собственные 5-10 функций для выполнения обычных вызовов sproc и упрощения преобразования типов данных и тогда вы вернетесь к тому, чтобы быть полностью контролируемым и не застряли в библиотеках, которые собираются взять еще 5yr для стабилизации.
Тем более, что у вас есть очень чистая схема - это довольно простые запросы и прямые обновления.
Я столкнулся с той же проблемой и, наконец, придумал решение. Основная идея состоит в том, чтобы предотвратить присоединение определенного типа навигационного класса к ObjectContext. Вот что я сделал:
public static void CustomApplyChanges (это Контекст ObjectContext, строка entitySetName, объект TEntity, Тип [] excludeTypes), где TEntity: IObjectWithChangeTracker
область обработки Начальное состояние сущности
foreach (IObjectWithChangeTracker changedEntity в entityIndex.AllEntities.Where(x = > x.ChangeTracker.State == ObjectState.Deleted && & ! ExcludeTypes.Contains(x.GetType()))){HandleDeletedEntity (контекст, entityIndex, allRelationships, changedEntity); }
foreach (IObjectWithChangeTracker changedEntity в entityIndex.AllEntities.Where(x = > x.ChangeTracker.State != ObjectState.Deleted & &! ExcludeTypes.Contains(x.GetType()))){HandleEntity (контекст, entityIndex, allRelationships, changedEntity); }
endregion
Тип [] excludeTypes = {typeof (Asset), typeof (Адрес), typeof (Region)};
rep.Entities.CustomApplyChanges(entity, excludeTypes); var changedEntry = rep.Context.ObjectStateManager.GetObjectStateEntries > (System.Data.EntityState.Added | System.Data.EntityState.Modified | System.Data.EntityState.Deleted); foreach (var e in changedEntry) { if (excludeTypes.Any(c = > c == e.Entity.GetType())) { rep.Context.Detach(e.Entity);//Отключить объекты без изменений } }
Я решил это, установив сброс идентификаторов внешних ключей, для которых необходимо установить значение Navigation для null, прежде чем сохранять.
... что-то вроде этого:
var countryToId = address.CountryToId;
var countryFromId = address.CountryFromId;
documentAddress.CountryTo = null;
documentAddress.CountryFrom = null;
documentAddress.CountryToId = countryToId;
documentAddress.CountryFromId = countryFromId;
Я получал эту ошибку, потому что я удалял записи объекта, повторяя его, а затем снова добавляя объект к новым данным.
Поскольку самообследование было включено на этом объекте, оно не позволяло добавлять запись с тем же ключом, даже если запись с этим ключом была удалена ранее.
Поскольку в этой ситуации мне не нужно самостоятельное отслеживание, я отключил его как:
dbcontext.entity.MergeOption = System.Data.Objects.MergeOption.NoTracking;