【发布时间】:2017-01-09 12:31:30
【问题描述】:
我在工作单元开始时开始会话并在结束时关闭。工作单元分布在多种方法中。
在一种方法中,我使用Get 方法加载实体。所以它位于会话缓存中。实体实例是方法的本地实例。所以当方法范围结束时,实体实例是不可访问的。但实体仍在会话缓存中。
现在,第二种方法创建实体的新实例并尝试删除它。这会按预期抛出NonUniqueObjectException。
以下是我可以想象但无法实施的解决方案:
public void Delete<T>(T instance) where T : BaseEntity
{
try
{
nhSession.Delete(instance);
}
catch(NonUniqueObjectException)
{
T instanceFromCache = GetInstanceFromCache<T>(instance);
nhSession.Evict(instanceFromCache);
nhSession.Delete(instance);
}
}
如果我能以某种方式从会话缓存中获取实体实例,我可以Evict 它并希望问题能够得到解决。但我无法实现我想象中的GetInstanceFromCache 方法。
我尝试使用nhSession.Get,但这对我的场景没有帮助。我的数据库中的主键列名不是“id”,而且跨表也不相同。在一个表中,它是“Field1”,在另一个表中是“Field2”。所以我不能使用像nhSession.Get(instance.Id) 这样的东西。我的Delete<T>(T instance) 方法接收要删除的实体实例作为参数。它没有收到要删除的主键值。
有关更多信息,请参阅我的other 问题。该问题讨论了更新问题以及我如何解决它;但场景类似。
编辑 1
“@Ricardo Peres”的回答不能按原样工作,但我稍微修改了他的代码。
public static TEntity GetInstanceFromCache<TEntity>(this ISession nhSession, object instance) where TEntity : BaseEntity
{
var sessionImpl = nhSession.GetSessionImplementation();
foreach(BaseEntity baseEntity in sessionImpl.PersistenceContext.EntityEntries.Keys)
{
if(baseEntity is TEntity)
{
TEntity instanceFromCache = (TEntity)baseEntity;
if(nhSession.GetIdentifier(instanceFromCache) == nhSession.GetIdentifier(instance))
return baseEntity as TEntity;
}
}
return null;
}
调用nhSession.GetIdentifier(instance) 会引发预期的异常TransientObjectException(“实例未与此会话关联”)。这是因为instance 对nhSession 来说是未知的。有什么方法可以获取与会话无关的实体标识符?
【问题讨论】:
标签: nhibernate