1

Я добавил строку в свою базу данных и возвратился с другим контекстом для ее обновления. У меня есть этот класс:Entity Framework Update Существующий объект

public abstract partial class DataManager<I, C> 
    where C : class, IDomainObject, I, new() where I : IDomainObject 

C может быть EntityObject, но этот класс этого не знает.

Мои Сохранить выглядит следующим образом:

public virtual bool Save(I _item) 
    { 
     bool rc = true; 
     try 
     { 
     var set = m_Context.GetObjectSet<I, C>(); 
     ObjectStateEntry stateEntry = null; 
     if(! m_Context.ObjectStateManager.TryGetObjectStateEntry((C) _item, out stateEntry)) 
     { 
      if(_item is EntityObject) 
      { 
        if (_item.IsNew) 
        { 
         set.AddObject((C) _item); 
        } 
        else 
        { 
         try 
         { 
          set.Attach((C) _item); 
         } 
         catch(Exception ex) 
         { 
          set.ApplyCurrentValues((C) _item); 
         } 

и так далее ...

В моем тестовом случае stateEntry не найден TryGetObjectStateEntry. Это, однако, EntityObject, и он не является новым (IsNew - это мой флаг), поэтому он переходит к другому. Вот моя проблема: set.Attach выдает эту ошибку

«Объект с тем же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом».

и в следующий момент, ApplyCurrentValues ​​бросает это один:

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

Как они могут быть истинными?

Дополнительная информация:

_item был создан Получить в другом контексте. Затем этот контекст был удален. В этот момент у _item был EntityState.Unchanged. Я применил к нему некоторые изменения, и он изменился на EntityState.Modified. (Я не ожидал этого, так как контекст (и его ObjectStateManager) должен был исчезнуть.) Во всяком случае, как только он доберется до Save (выше), это состояние (как сообщается отладчиком) изменено, но у меня есть к тому времени новый контекст. Если в этот момент я получу список ВСЕХ объектов ObjectStateEntries (добавлено, удалено, изменено, без изменений), их будет только два, а _item - не один из них, как отчеты ApplyCurrentValues, но он не может быть прикреплен, потому что «это тоже есть! ». Возможно, проблема в том, что она все еще привязана к старой ObjectStateManager (может ли быть какая-то ссылка, которая не позволит ObjectStateManager удалять?).

+0

Вы вызываете context.SaveChanges() дважды? –

+0

@DannyVarod - я использую UnitOfWork, в котором я вызываю SaveChanges только когда я удаляю Unit, и я удаляю контекст одновременно. Это веб-приложение, поэтому у него очень короткие жизненные циклы для контекста. WcfService израсходовал UnitOfWork, чтобы получить _item (что «Получить в другом контексте», о котором я упоминал). Но как только мы доберемся до Save, нет возможности для SaveChanges для вызова дважды. –

+0

И вы уверены, что вы не получаете то же самое Uow в два раза из своей инфраструктуры инъекций зависимостей? –

ответ

0

Проблема заключается в том, что каждый раз, когда инициализируется db-context, он берет строки из базы данных и строки foreach, назначает ключ сущности. что означает, что одна и та же строка, полученная 2-битным контекстом, будет иметь 2 разных сущности. ключ объекта как идентификатор в структуре сущности, и он используется вместо идентификатора рассматриваемого объекта. Но ограничения таблиц, хотя и сохраняются (нет дублирующего первичного ключа) Надеюсь, что это имеет смысл.

+0

Ответ имеет смысл, но вопрос в том, как может тот же объект в том же контексте сообщаться Attach как «уже существует» и сообщается ApplyCurrentValues ​​как «не может быть найден»? –

+0

Я честно не знаю, что вызывает вторую проблему.но попытайтесь решить первую, и это, возможно, связано со вторым. Я предлагаю (быстрый тест), что вы используете статический dbcontext – Boomer

0

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

Если организация уже есть в БД, попробуйте:

  1. Либо установка навигационных свойств организации обнулить и установить только свойства OrganizationId.

  2. Или загрузить организационную сущность из БД и поместить ее в навигационные реквизиты.

Если организация не в БД:

Используйте тот же экземпляр (бросить один прочь и заменить его другим).

Смежные вопросы