NHibernate:如何从会话缓存中获取实体实例?

NHibernate:如何从会话缓存中获取实体实例?,nhibernate,Nhibernate,我在工作单元开始时开始会话,在结束时结束会话。工作单元可以跨多种方法进行扩展 在一种方法中,我使用Get方法加载实体。所以它位于会话缓存中。实体实例是该方法的本地实例。所以当方法作用域结束时,实体实例是不可访问的。但实体仍在会话缓存中 现在,第二个方法创建实体的新实例并尝试删除它。这将按预期引发ununiqueObjectException 以下是我可以想象但无法实施的解决方案: public void Delete<T>(T instance) where T : BaseEnti

我在工作单元开始时开始会话,在结束时结束会话。工作单元可以跨多种方法进行扩展

在一种方法中,我使用
Get
方法加载实体。所以它位于会话缓存中。实体实例是该方法的本地实例。所以当方法作用域结束时,实体实例是不可访问的。但实体仍在会话缓存中

现在,第二个方法创建实体的新实例并尝试删除它。这将按预期引发
ununiqueObjectException

以下是我可以想象但无法实施的解决方案:

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

调用
nhSession.GetIdentifier(实例)
会引发预期的异常
TransientObjectException
(“实例未与此会话关联”)。这是因为
instance
nhSession
是未知的。有没有办法获取与会话无关的实体标识符?

您需要获取PersistenceContext,如下所示:

using System.Linq;
using NHibernate;   

public static T GetInstanceFromCache<T>(this ISession session, object key) where T : class
{
    var entity = session.GetSessionImplementation().PersistenceContext.EntitiesByKey.SingleOrDefault(x => x.Value is T && x.Key.Identifier == key);
    return entity as T;
}
使用System.Linq;
使用NHibernate;
公共静态T GetInstanceFromCache(此ISession会话,对象键),其中T:class
{
var entity=session.GetSessionImplementation().PersistenceContext.EntitiesByKey.SingleOrDefault(x=>x.Value为T&&x.Key.Identifier==Key);
将实体返回为T;
}
通过@ricardopers,我能够解决这个问题。但确切的代码对我来说不起作用。我对它做了如下修改:

public static TEntity GetInstanceFromCache<TEntity>(this ISession nhSession, object instance) where TEntity : BaseEntity
{
    object detachedIdentifier = GetDetachedEntityId<TEntity>(instance, nhSession.SessionFactory);

    var sessionImpl = nhSession.GetSessionImplementation();
    foreach(BaseEntity baseEntity in sessionImpl.PersistenceContext.EntityEntries.Keys)
    {
        if(baseEntity is TEntity)
        {
            TEntity instanceFromCache = (TEntity)baseEntity;
            string idFromCache = Convert.ToString(nhSession.GetIdentifier(instanceFromCache));
            string idNew = Convert.ToString(detachedIdentifier);
            if(idFromCache == idNew)
                return baseEntity as TEntity;
        }
    }
    return null;

    //Another way-----------------------------
    //var entity = nhSession.GetSessionImplementation().PersistenceContext.EntitiesByKey.SingleOrDefault(x => x.Value is TEntity && Convert.ToString(x.Key.Identifier) == Convert.ToString(detachedIdentifier));
    //return entity.Value as TEntity;
    //Another way-----------------------------
}

public static object GetDetachedEntityId<TEntity>(object instance, ISessionFactory sessionFactory) where TEntity : BaseEntity
{
    Type entityType‌​ = typeof(TEntity);
    var entityName = (sessionFactory as ISessionFactoryImplementor).TryGetGuessEntityName(entityType‌​);
    AbstractEntityPersister persister = (sessionFactory as ISessionFactoryImplementor).TryGetEntityPersister(entityName‌​) as AbstractEntityPersister;
    if(persister != null)
    {
        PropertyInfo idPropertyInfo = entityType.GetProperty(persister.IdentifierPropertyName);
        object identifier = idPropertyInfo.GetValue(instance, null);
        return identifier;
    }
    return null;
}
公共静态TEntity GetInstanceFromCache(此ISession nhSession,对象实例),其中TEntity:BaseEntity
{
object detachedIdentifier=GetDetachedEntityId(实例,nhSession.SessionFactory);
var sessionImpl=nhSession.GetSessionImplementation();
foreach(sessionImpl.PersistenceContext.EntityEntries.Keys中的BaseEntity BaseEntity)
{
if(基本实体为TEntity)
{
TEntity instanceFromCache=(TEntity)baseEntity;
字符串idFromCache=Convert.ToString(nhSession.GetIdentifier(instanceFromCache));
字符串idNew=Convert.ToString(detachedIdentifier);
if(idFromCache==idNew)
返回基本实体作为tenty;
}
}
返回null;
//另一种方式-----------------------------
//var entity=nhSession.GetSessionImplementation().PersistenceContext.EntitiesByKey.SingleOrDefault(x=>x.值为tenty&&Convert.ToString(x.Key.Identifier)==Convert.ToString(detachedIdentifier));
//返回实体。值为tenty;
//另一种方式-----------------------------
}
公共静态对象GetDetachedEdentTityId(对象实例,ISessionFactory sessionFactory),其中tenty:BaseEntity
{
类型实体类型‌​ = 类型(张力);
变量entityName=(sessionFactory作为ISessionFactoryImplementor)。TryGetGuessEntityName(entityType‌​);
AbstractEntityPersister=(sessionFactory作为ISessionFactoryImplementor)。TryGetEntityPersister(entityName‌​) 作为抽象主义者;
if(persister!=null)
{
PropertyInfo idPropertyInfo=entityType.GetProperty(persister.IdentifierPropertyName);
对象标识符=idPropertyInfo.GetValue(实例,null);
返回标识符;
}
返回null;
}
如果是代理:。
public static TEntity GetInstanceFromCache<TEntity>(this ISession nhSession, object instance) where TEntity : BaseEntity
{
    object detachedIdentifier = GetDetachedEntityId<TEntity>(instance, nhSession.SessionFactory);

    var sessionImpl = nhSession.GetSessionImplementation();
    foreach(BaseEntity baseEntity in sessionImpl.PersistenceContext.EntityEntries.Keys)
    {
        if(baseEntity is TEntity)
        {
            TEntity instanceFromCache = (TEntity)baseEntity;
            string idFromCache = Convert.ToString(nhSession.GetIdentifier(instanceFromCache));
            string idNew = Convert.ToString(detachedIdentifier);
            if(idFromCache == idNew)
                return baseEntity as TEntity;
        }
    }
    return null;

    //Another way-----------------------------
    //var entity = nhSession.GetSessionImplementation().PersistenceContext.EntitiesByKey.SingleOrDefault(x => x.Value is TEntity && Convert.ToString(x.Key.Identifier) == Convert.ToString(detachedIdentifier));
    //return entity.Value as TEntity;
    //Another way-----------------------------
}

public static object GetDetachedEntityId<TEntity>(object instance, ISessionFactory sessionFactory) where TEntity : BaseEntity
{
    Type entityType‌​ = typeof(TEntity);
    var entityName = (sessionFactory as ISessionFactoryImplementor).TryGetGuessEntityName(entityType‌​);
    AbstractEntityPersister persister = (sessionFactory as ISessionFactoryImplementor).TryGetEntityPersister(entityName‌​) as AbstractEntityPersister;
    if(persister != null)
    {
        PropertyInfo idPropertyInfo = entityType.GetProperty(persister.IdentifierPropertyName);
        object identifier = idPropertyInfo.GetValue(instance, null);
        return identifier;
    }
    return null;
}