为什么 EntityAspect.RemoveFromManager 没有完全删除?
Why does EntityAspect.RemoveFromManager not remove completely?
我正在使用 Silverlight 4 和 DevForce 6.1.11.0
我有一些实现 EntityAspect 的 POCO 类。
我使用 WebClient 从不同的设备获取这些实体。这些设备没有 DevForce 服务器。
将实体添加到实体管理器时,我首先使用 entityManager.FindEntities<PocoSomeEntity>(EntityState.AllButDetached)
检查缓存中是否不存在具有该键的实体。然后我创建实体并像这样添加它:
entityManager.AddEntity(entity);
entity.EntityAspect.AcceptChanges();
我可以添加、修改和删除实体并将它们保存回设备 - 目前没有问题。
最近我使用 entity.EntityAspect.RemoveFromManager(true);
实现了 "clear cache"
如果我删除一个实体(EntityAspect.Delete()
),这似乎是可行的,然后将其从管理器中删除,然后尝试将其重新加载。在重新加载的实体上调用 EntityAspect.AcceptChanges()
时,它会抛出一个 "already exists"异常。
如何解决这个问题?
编辑
抛出异常的是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);
编辑2
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
}
}
解决方法是使用 FindEntity() 仔细检查。如果存在,则 re-populate 其属性并将其添加回管理器。
// 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();
}
编辑
如果我删除两个或更多相同类型的实体,解决方法将不起作用。
您似乎发现了 DevForce SL 版本中的一个错误。问题在于 DF 如何处理实体上的 EntityKey,因为它没有为某些实体状态和实体版本设置基础 属性 值。在这里,尽管执行了 Add 和 AcceptChanges,但 DF 仍然没有为 EntityKey 设置支持字段,这导致了以后的奇怪行为。
有几个解决方法可能比您实施的查找逻辑更容易。
首先是对这些 POCO 实体使用 Attach 而不是 Add/AcceptChanges。将实体附加为 "Unchanged" 时遵循的代码路径 DF 确实确保正确设置了 EntityKey。
manager.AttachEntity(entity);
如果用例要求实体处于 "Added" 状态,另一个解决方法是在执行 AcceptChanges 后调用 EntityKey getter,这确保了 EntityKey 支持字段设置正确。例如,
manager.AddEntity(entity);
entity.EntityAspect.AcceptChanges();
var ek = entity.EntityAspect.EntityKey;
我正在使用 Silverlight 4 和 DevForce 6.1.11.0
我有一些实现 EntityAspect 的 POCO 类。
我使用 WebClient 从不同的设备获取这些实体。这些设备没有 DevForce 服务器。
将实体添加到实体管理器时,我首先使用 entityManager.FindEntities<PocoSomeEntity>(EntityState.AllButDetached)
检查缓存中是否不存在具有该键的实体。然后我创建实体并像这样添加它:
entityManager.AddEntity(entity);
entity.EntityAspect.AcceptChanges();
我可以添加、修改和删除实体并将它们保存回设备 - 目前没有问题。
最近我使用 entity.EntityAspect.RemoveFromManager(true);
实现了 "clear cache"
如果我删除一个实体(EntityAspect.Delete()
),这似乎是可行的,然后将其从管理器中删除,然后尝试将其重新加载。在重新加载的实体上调用 EntityAspect.AcceptChanges()
时,它会抛出一个 "already exists"异常。
如何解决这个问题?
编辑
抛出异常的是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);
编辑2
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
}
}
解决方法是使用 FindEntity() 仔细检查。如果存在,则 re-populate 其属性并将其添加回管理器。
// 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();
}
编辑
如果我删除两个或更多相同类型的实体,解决方法将不起作用。
您似乎发现了 DevForce SL 版本中的一个错误。问题在于 DF 如何处理实体上的 EntityKey,因为它没有为某些实体状态和实体版本设置基础 属性 值。在这里,尽管执行了 Add 和 AcceptChanges,但 DF 仍然没有为 EntityKey 设置支持字段,这导致了以后的奇怪行为。
有几个解决方法可能比您实施的查找逻辑更容易。
首先是对这些 POCO 实体使用 Attach 而不是 Add/AcceptChanges。将实体附加为 "Unchanged" 时遵循的代码路径 DF 确实确保正确设置了 EntityKey。
manager.AttachEntity(entity);
如果用例要求实体处于 "Added" 状态,另一个解决方法是在执行 AcceptChanges 后调用 EntityKey getter,这确保了 EntityKey 支持字段设置正确。例如,
manager.AddEntity(entity); entity.EntityAspect.AcceptChanges(); var ek = entity.EntityAspect.EntityKey;