为什么EntityAspect.RemoveFromManager不能完全删除?
我正在使用Silverlight 4和DevForce 6.1.11.0为什么EntityAspect.RemoveFromManager不能完全删除?
我有一些实现EntityAspect的POCO类。
我使用WebClient从不同的设备获取这些实体。这些设备没有DevForce服务器。 将实体添加到实体管理器时,首先使用entityManager.FindEntities<PocoSomeEntity>(EntityState.AllButDetached)
检查具有密钥的实体不存在于高速缓存中。然后,我创建实体并添加这样的:
entityManager.AddEntity(entity);
entity.EntityAspect.AcceptChanges();
我可以添加,修改和删除实体和将其保存到设备 - 到目前为止,没有任何问题。
最近我实现了一个“清除缓存”使用entity.EntityAspect.RemoveFromManager(true);
这似乎工作期望,如果我删除一个实体(EntityAspect.Delete()
),然后从管理员删除它,然后尝试加载回。当重装调用EntityAspect.AcceptChanges()
实体,它会抛出一个“已经存在”异常。
我该如何解决此问题?
编辑
这是AddEntity()
抛出异常。
这里是堆栈跟踪:
我的实体具有复合键。 我搜索缓存,但我什么也没找到:
// 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
}
}
看起来您已经发现了SL版本DevForce中的一个错误。问题在于DF如何处理实体上的EntityKey,因为它没有为某些实体状态和实体版本设置基础属性值。在这里,尽管执行了Add和AcceptChanges,但DF仍然没有为EntityKey设置后台字段,这会导致稍后的奇怪行为。
有几个解决方法可能比您实施的查找逻辑更容易。
-
第一个是对这些POCO实体使用Attach而不是Add/AcceptChanges。代码路径DF在实体被连接时跟随,因为“不变”确保EntityKey设置正确。
manager.AttachEntity(entity);
-
如果用例要求的实体处于“增加”状态时,另一个解决方法是做一个的AcceptChanges,这确保了的EntityKey支持字段被正确地设置之后调用的EntityKey吸气剂。例如,
manager.AddEntity(entity); entity.EntityAspect.AcceptChanges(); var ek = entity.EntityAspect.EntityKey;
你救了我的一天!我去了AttachEntity解决方法,它似乎完美。 –
一种解决方法要再次检查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();
}
编辑
如果我删除了相同类型的两个或多个实体的解决方法不起作用。
我没有在测试中看到了这个问题。如果密钥已经存在于EM缓存中,则在执行AddEntity()时将抛出异常。在添加之前检查EntityKey的值 - 如果它是类似于0或可能有助于缩小问题范围的tempid,或者提供更多信息来诊断它。 –
我在帖子中增加了更多细节。在进行AddEntity之前,实体没有EntityAspect,我无法检查EntityKey。在AddEntity之后,它抛出异常。在此之后,EntityKey是正确的,但实体已分离。 –
错误消息中显示的实体键是否是正确的键?我仍然想知道它是否可能被设置为零或由临时ID生成器分配负ID。如果看起来和预期的一样,你也可以用正确的键值构造一个EntityKey,然后调用em.FindEntity(entityKey)来查看是否在缓存中找到匹配项。 –