【问题标题】:NHibernate: How to get entity instance from session cache?NHibernate:如何从会话缓存中获取实体实例?
【发布时间】: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&lt;T&gt;(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(“实例未与此会话关联”)。这是因为instancenhSession 来说是未知的。有什么方法可以获取与会话无关的实体标识符?

【问题讨论】:

标签: nhibernate


【解决方案1】:

你需要获取 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;
}

【讨论】:

    【解决方案2】:

    通过@RicardoPeres 的code provided,我能够解决它。但是确切的代码对我不起作用。我稍微修改了一下:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-24
      • 2011-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      • 1970-01-01
      • 2011-07-15
      相关资源
      最近更新 更多