2016-01-06 5 views
1

Я использую Silverlight 4 и DevForce 6.1.11.0Почему EntityAspect.RemoveFromManager не полностью удаляется?

У меня есть классы POCO, которые реализуют EntityAspect.

Я использую WebClient для получения этих объектов с разных устройств. У этих устройств нет сервера DevForce. При добавлении объектов к менеджеру сущности, я сначала проверить, что объект с ключом не существует в кэше, используя entityManager.FindEntities<PocoSomeEntity>(EntityState.AllButDetached). Затем я создаю объект и добавить его так:

entityManager.AddEntity(entity); 
entity.EntityAspect.AcceptChanges(); 

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

В последнее время я реализовал «очистить кэш» с помощью entity.EntityAspect.RemoveFromManager(true); Это, казалось, работать ожидать, если удалить объект (EntityAspect.Delete()), а затем удалить его из диспетчера, а затем попытаться загрузить его обратно. При вызове EntityAspect.AcceptChanges() на Reloaded объект, он выбрасывает исключение «уже существует».

Как устранить эту проблему?

EDIT

Это AddEntity(), что бросает исключение.

Вот трассировки стека:

at IdeaBlade.EntityModel.EntityGroup.AddToKeyMap(EntityAspect aspect) 
    at IdeaBlade.EntityModel.EntityGroup.AddEntityCore(EntityAspect aspect) 
    at IdeaBlade.EntityModel.EntityGroup.AddAttachedEntity(EntityAspect aspect, EntityState entityState) 
    at IdeaBlade.EntityModel.EntityManager.AttachEntityAspect(EntityAspect aspect, EntityState entityState) 
    at IdeaBlade.EntityModel.EntityManager.AttachEntity(Object entity, EntityState entityState) 
    at IdeaBlade.EntityModel.EntityManager.AddEntity(Object entity) 
    at ... 

Моя сущность имеет составной ключ. Я искал тайник, но я ничего не нашел:

// returns nothing 
var instancesInManager = entityManager.FindEntities<PocoSomeEntity>(EntityState.AllButDetached).Where(i => i.p_key1 == 41 && i.p_key2 == 5448); 
// returns nothing 
var detachedInstancesInManager = entityManager.FindEntities<PocoSomeEntity>(EntityState.Detached).Where(i => i.p_key1 == 41 && i.p_key2 == 5448); 

Я также поиск без ключа, но не нашел ничего, что могло бы объяснить такое поведение:

// returns instances, but none have keys with zeros or the key that I am looking for. 
var instancesInManager = entityManager.FindEntities<PocoSomeEntity>(EntityState.AllButDetached); 
// returns no results 
var detachedInstancesInManager = entityManager.FindEntities<PocoSomeEntity>(EntityState.Detached); 

EDIT2

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.ComponentModel.DataAnnotations; 
using System.Runtime.Serialization; 
using IdeaBlade.Core.DomainServices; 
using IdeaBlade.EntityModel; 
using IbVal = IdeaBlade.Validation; 

namespace ServerModel 
{ 
    [DataContract(IsReference = true)] 
    public class PocoSomeEntity : IKnownType, IHasPocoEntityAspect, INotifyPropertyChanged 
    { 
     public PocoSomeEntity() { } 

     private int m_key1; 

     [Key] 
     public int p_key1 
     { 
      get { return m_key1; } 
      set { m_key1 = value; OnPropertyChanged("p_key1"); } 
     } 

     private int m_key2; 
     [Key] 
     public int p_key2 
     { 
      get { return m_key2; } 
      set { m_key2 = value; OnPropertyChanged("p_key2"); } 
     } 

... 

     #region IHasPocoEntityAspect Members 

     [Display(AutoGenerateField = false)] 
     [IgnoreDataMember] 
     public IdeaBlade.EntityModel.EntityAspect EntityAspect 
     { 
      get; 
      set; 
     } 

     #endregion 

     #region INotifyPropertyChanged Members 

     /// <summary> 
     /// This interface implementation is needed if you want EntityManager to automatically listen 
     /// to any property change. 
     /// </summary> 

     public event PropertyChangedEventHandler PropertyChanged; 

     protected void OnPropertyChanged(String propertyName) 
     { 
      var handler = PropertyChanged; 
      if (handler != null) 
      { 
       var args = new PropertyChangedEventArgs(propertyName); 
       handler(this, args); 
      } 
     } 

     #endregion 
    } 
} 
+0

Я не вижу этот вопрос в тестировании. Исключение будет выбрано при выполнении AddEntity(), если ключ уже существует в кеше EM. Проверьте значение EntityKey перед выполнением добавления - если это что-то вроде 0 или шаблонное, что может помочь сузить проблему или дать нам больше информации для ее диагностики. –

+0

Я добавил более подробную информацию к сообщению. Перед выполнением AddEntity у объекта нет EntityAspect, и я не могу проверить EntityKey. После AddEntity он выдает исключение. После этого EntityKey прав, но объект отсоединен. –

+0

Является ли ключ объекта указанным в сообщении об ошибке правильной клавишей? Мне все еще интересно, возможно ли установить нули или присвоить отрицательный идентификатор генератором временного идентификатора. Если он выглядит так, как ожидалось, вы также можете построить EntityKey из правильных значений ключа, а затем вызвать em.FindEntity (entityKey), чтобы узнать, найдет ли это совпадение в кеше. –

ответ

1

Похоже, вы обнаружили ошибку в версии SL DevForce. Проблема заключается в том, как DF обрабатывает EntityKey для объекта, поскольку он не устанавливает базовое значение свойства для определенных состояний сущностей и сущностей. Здесь, несмотря на выполнение добавления, за которым следует AcceptChanges, DF все еще не установил поле поддержки для EntityKey, что впоследствии приведет к нечетному поведению.

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

  • Первый заключается в использовании Attach, а не Add/AcceptChanges для этих объектов POCO. Код DF кода следует, когда объект привязан как «Без изменений», гарантирует, что EntityKey установлен правильно.

    manager.AttachEntity(entity); 
    
  • Если случай использования требует, чтобы субъекты были в состоянии «Добавлено», другой обходной путь, чтобы вызвать поглотитель EntityKey после выполнения AcceptChanges, что обеспечивает поле EntityKey Подложка установлен правильно. Например,

    manager.AddEntity(entity); 
    entity.EntityAspect.AcceptChanges(); 
    var ek = entity.EntityAspect.EntityKey; 
    
+0

Ты спас мой день! Я пошел на обходной путь AttachEntity и, похоже, работает отлично. –

0

Обходной бы дважды проверить с помощью FindEntity(). Если он существует, то повторно заново заполнить его свойства и добавить его обратно в менеджер.

// Check if entity already exists in manager 
var instancesInManager = entityManager.FindEntities<PocoSomeEntity>(EntityState.AllButDetached).Where(i => i.p_key1==key1 && i.p_key2==key2); 
var entity = instancesInManager.FirstOrDefault(); 
if (entity == null) 
{ 
     PocoSomeEntity i; 

     // Double check if entity really exists in manager :) 
     var doubleCheck = entityManager.FindEntity(new EntityKey(typeof(PocoSomeEntity), key1, key2)); 
     if (doubleCheck != null) 
     { 
       i = (doubleCheck as PocoSomeEntity); 
     } 
     else 
       // If it does not exists, then we can create it 
       i = new PocoSomeEntity(); 

     i.p_key1 = key1; 
     i.p_key2 = key2; 

     // populate or re-populate entity properties 
     ... 

     entityManager.AddEntity(i); 
     i.EntityAspect.AcceptChanges(); 
} 

EDIT

Обойти не работает, если удалить два или более объектов одного и того же типа.

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