在一个会话中加载的实体不会被缓存

时间:2013-12-30 09:37:44

标签: nhibernate caching

有两个静态数据实体(需要在内存中完全加载)

[Class(...)]
public class AttributeInfo : EntityBase
{
    [Id(0, Name = "Id", Column = "id", Type = "int")]
    [Generator(1, Class = "native")]
    public override int Id { get; set; }

    public AttributeInfo () {}

}

[Class(...)]
public class Item : EntityBase
{
    [Id(0, Name = "Id", Column = "id", Type = "int")]
    [Generator(1, Class = "native")]
    public override int Id { get; set; }

    [ManyToOne(Name = "...", Column = "...", Lazy = Laziness.False)]
    public virtual AttributeInfo Attrs { set; get; }

    public Item() { }
}

我打开会话并开始交易:

   using (var s = sessionFactory.OpenSession())
   using (var tr = s.BeginTransaction())
   {

我加载所有属性:

   s.CreateCriteria< AttributeInfo>().List().Cast< AttributeInfo>().ToArray()

所有项目:

   s.CreateCriteria< Item>().List().Cast< Item>().ToArray()

问题是没有使用缓存,对于每个项目,nhibernate都会从AttributeInfo查询中创建一个select。

我知道静态数据加载的优化没有什么大的价值。但我想了解nhibernate缓存是如何工作的。

那么我做错了什么?

1 个答案:

答案 0 :(得分:0)

首先,您的示例适用于我,而不会为每个属性生成查询。只有当我不加载所有属性时,第二个查询当然会逐个加载所有属性,因为映射中没有延迟设置。

也许您正在使用旧版本的nh或在其他地方使用其他设置?

无论如何,最好的方法是为非惰性集合定义获取模式。

 [ManyToOne(Lazy = Laziness.False, Fetch=FetchMode.Join)]

这将强制nh创建一个连接属性查询,实际上一次解析了项目+属性。使用此解决方案,您无需(预)加载所有属性,即使是那些您可能不需要的属性......

提示:

要观看第一级缓存中存在的元素,您可以使用简单的扩展名

public static class SessionExtensions
{
    public static IEnumerable<T> FirstLevelCache<T>(this ISession session)
    {
        ISessionImplementor impl = session.GetSessionImplementation();
        IPersistenceContext pc = impl.PersistenceContext;

        foreach (Object key in pc.EntityEntries.Keys)
        {
            if (key is T)
            {
                yield return ((T) key);
            }
        }
    }
}

现在

var attributes = session.CreateCriteria<AttributeInfo>().List().Cast<AttributeInfo>().ToArray();

var cached = session.FirstLevelCache<AttributeInfo>().ToList();

cached应包含属性。