Самопроверка объектов - AcceptChanges не может продолжаться, потому что значения ключа объекта конфликтуют с другим объектом в ObjectStateManager - PullRequest
12 голосов
/ 28 июля 2010

Я застрял с этой проблемой уже более недели.Надеюсь, кто-нибудь может указать мне правильное направление.

Я начну с краткого описания моей схемы.

Актив 1 ---> 1 Адрес * -> 1 Область * -> 1 Регион * -> 1 Страна

Пакет 1 -> * Актив

Использование объекта самоконтроля (STE) + WCF.

Шаги:

  1. Хранилище данных вызовов для списка активов.
  2. Хранилище данных вызовов для списка пакетов.
  3. Пользователь выбирает пакет и присваивает ему некоторые активы.
  4. Сохранить пакет.

На шаге 2 для вызова используется активная загрузка адресов.

from p in context.Assets.Include("Address.Area.Region.Country")

Это ошибка при попытке вызвать

context.Packages.ApplyChanges(package)

AcceptChanges не может продолжаться, поскольку значения ключей объекта конфликтуют с другим объектом в ObjectStateManager.Убедитесь, что значения ключей уникальны, прежде чем вызывать AcceptChanges.

EDIT

После прослушивания я обнаружил, что это проблема STE.Проблема в том, что вы не можете сохранить график, который содержит несколько экземпляров одной и той же сущности, как указано здесь .Вот мой вопрос.

Как я могу добавить объект в свою коллекцию объектов.Новый объект может иметь связанные объекты, которые содержат тот же ключ, что и ключ в коллекции.Т.е. добавить новый актив, который может содержать тот же адрес, область, регион или страну.

Вот мои ограничения:

  1. Я должен использовать навигационную коллекцию, потому что онавлияет на пользовательский интерфейс.
  2. Я не могу предварительно выбрать все объекты, которые будут задействованы, поскольку набор данных слишком велик.
  3. Я должен иметь возможность делать моментальные снимки объекта в любое времячтобы сохранить историю и использовать ее для отмены любых изменений.

Мне известны возможные решения, предложенные Diego B Vega , но это не варианты, которые яможно использовать для моего решения.У кого-нибудь есть другие идеи?

Ответы [ 5 ]

8 голосов
/ 06 октября 2010

К вашему сведению, я написал сообщение в блоге с некоторыми дополнительными предложениями, на которые я уже ответил на форумах EF. Здесь - это запись в блоге.

8 голосов
/ 05 августа 2010

Рассматривали ли вы просто отказаться от ORM и вернуться к нормальному доступу, если вы понимаете, что я имею в виду: -)

Не шучу - к тому времени, когда вы боретесь с одной единственной проблемой, такой как эта (которая пахнет багом ORM больше всего на свете), вы могли бы развернуть свои собственные 5-10 функций для выполнения обычных вызовов sproc и более простого преобразования типов данных и тогда вы вернетесь к полному контролю и не будете застревать в библиотеках, для стабилизации которых понадобится еще 5 лет.

Тем более, что у вас, кажется, очень чистая схема, то есть довольно простые запросы и прямые обновления.

3 голосов
/ 13 августа 2010

Я столкнулся с той же проблемой и, наконец, нашел решение.Основная идея состоит в том, чтобы предотвратить присоединение определенного типа навигационного класса к ObjectContext.Вот что я сделал:

  1. Изменен шаблон context.tt, чтобы сделать класс SelfTrackingEntitiesContextExtensions частичным.
  2. Скопируйте 2 функции ApplyChanges во вновь созданный Custom.Context.Extension.cs и переименуйте.их как CustomApplyChanges.Каждый из них будет иметь один дополнительный параметр в виде массива типа

public static void CustomApplyChanges (этот контекст ObjectContext, строка entitySetName, сущность TEntity, Type [] excludeTypes ) где TEntity: IObjectWithChangeTracker

Добавить условие в цикл for для исключения любого типа класса, содержащегося в массиве excludeTypes.

регион Обрабатывать начальное состояние объекта

foreach (IObjectWithChangeTracker changeEntity в entityIndex.AllEntities.Where (x => x.ChangeTracker.State == ObjectState.Deleted && ! ExcludeTypes.Contains (x.GetType ()))) {HandleDeletedEntity (context, entityIndex, allRelationships, updatedEntity);}

foreach (IObjectWithChangeTracker changeEntity в entityIndex.AllEntities.Where (x => x.ChangeTracker.State! = ObjectState.Deleted &&! ExcludeTypes.Contains (x.GetType ()))) {HandleEntity (context, entityIndex, allRelationships, ChangeEntity);}

endregion

Использование

Type [] excludeTypes = {typeof (Asset), typeof (Address), typeof (Region)};

rep.Entities.CustomApplyChanges(entity, excludeTypes);var changeEntry = rep.Context.ObjectStateManager.GetObjectStateEntries> (System.Data.EntityState.Added | System.Data.EntityState.Modified | System.Data.EntityState.Deleted);foreach (варьируется в changeEntry) {if (excludeTypes.Any (c => c == e.Entity.GetType ())) {rep.Context.Detach (e.Entity);// отсоединяем неизмененные объекты}}

1 голос
/ 11 мая 2013

Я решил эту проблему установкой сброса идентификаторов внешних ключей, для чего перед сохранением потребовалось установить значение навигации равным нулю.

... примерно так:

var countryToId = address.CountryToId;
var countryFromId = address.CountryFromId;
documentAddress.CountryTo = null;
documentAddress.CountryFrom = null;
documentAddress.CountryToId = countryToId;
documentAddress.CountryFromId = countryFromId;
0 голосов
/ 22 апреля 2014

Я получал эту ошибку, потому что я удалял записи объекта, перезаполнял его, а затем заполнял объект новыми данными.

Поскольку для этой сущности было включено самотрекинг, добавлениезапись с тем же ключом, хотя запись с этим ключом была удалена ранее.

Поскольку в этой ситуации мне не требовалось самостоятельное отслеживание, я отключил ее как:

dbcontext.entity.MergeOption = System.Data.Objects.MergeOption.NoTracking;
...