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

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

本文介绍了NHibernate:如何从会话缓存中获取实体实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在工作单元开始时开始会话,在工作结束时结束.工作单元可采用多种方法保存.

I start the session at the start of unit of work and close at the end of it. Unit of work is spreed across multiple methods.

在一种方法中,我使用Get方法加载实体.因此,这位于会话缓存中.实体实例是该方法的本地对象.因此,当方法作用域结束时,实体实例将不可访问.但是实体仍在会话缓存中.

In one method, I load the entity using Get method. So this sits in session cache. Entity instance is local to the method. So when method scope ends, entity instance is not accessible. But entity is still in session cache.

现在,第二种方法创建实体的新实例并尝试将其删除.这将按预期抛出NonUniqueObjectException.

Now, second method creates new instance of entity and tries to delete it. This throws NonUniqueObjectException as expected.

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

Following is the solution I can imagine, but not able to implement:

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方法.

If I can get the entity instance from session cache somehow, I can Evict it and hopefully the problem will be solved. But I am not able to implement my imaginary GetInstanceFromCache method.

我尝试使用nhSession.Get,但这对我的情况没有帮助.我的数据库中的主键列名称不是"id",并且在表之间也不相同.在一个表中,它是"Field1",在另一个表中,它是"Field2".因此,我不能使用nhSession.Get(instance.Id)之类的东西.我的Delete<T>(T instance)方法接收要删除的实体实例作为参数.它不接收要删除的主键的值.

I tried using nhSession.Get, but that is not helpful in my scenario. Primary key column name in my database is NOT "id" and also it is not same across tables. In one table, it is "Field1" and in other it is "Field2". So I cannot use something like nhSession.Get(instance.Id). My Delete<T>(T instance) method receives entity instance to delete as parameter. It does not receive value of primary key to delete.

有关更多信息,请参阅我的其他问题.这个问题讨论了有关UPDATE的问题以及我如何解决它.但是情况是相似的.

For more info, please refer my other question. That question discusses about UPDATE issue and how I fixed it; but scenario is similar.

"@ Ricardo Peres"的答案无法正常运行,但我对其代码进行了一些修改.

Answer by "@Ricardo Peres" does not work as is, but I modified his code a little.

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是未知的.有什么方法可以获取与会话无关的实体的标识符?

The call nhSession.GetIdentifier(instance) throws an exception TransientObjectException ("The instance was not associated with this session") which is expected. This is because instance is unknown to nhSession. Any way to get identifier of entity that is NOT associated with session?

推荐答案

您需要掌握PersistenceContext,如下所示:

You need to get hold of the PersistenceContext, like this:

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

这篇关于NHibernate:如何从会话缓存中获取实体实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 01:50