silverlight-4.0devforce

Why does EntityAspect.RemoveFromManager not remove completely?


I am using Silverlight 4 and DevForce 6.1.11.0

I have some POCO classes that implement EntityAspect.

I use WebClient to get these entities from different devices. These devices do not have a DevForce server. When adding the entities to the entity manager, I first check that a entity with the key does not exist in cache using entityManager.FindEntities<PocoSomeEntity>(EntityState.AllButDetached). Then I create the entity and add it like this:

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

I can add, modify and delete entities and save them back to the devices - no problems so far.

Lately I implemented a "clear cache" using entity.EntityAspect.RemoveFromManager(true); This seemed to work expect if I delete a entity (EntityAspect.Delete()), then remove it from the manager and then try to load it back in. When calling EntityAspect.AcceptChanges() on the reloaded entity, it throws a "already exists" exception.

How do I workaround this issue?

EDIT

It is AddEntity() that throws the exception.

Here is the stack trace:

   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 ...

My entity has a composite key. I searched the cache but I found nothing:

// 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);

I also search without the key but found nothing that could explain this behavior:

// 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
    }
}

Solution

  • It looks like you've uncovered a bug in the SL version of DevForce. The issue is in how DF handles the EntityKey on an entity, as it doesn't set the underlying property value for certain entity states and entity versions. Here, despite doing an Add followed by AcceptChanges, DF has still not set the backing field for the EntityKey, which causes the odd behavior later on.

    There are a couple of workarounds which might be easier than the Find logic you've implemented.