有两个静态数据实体(需要在内存中完全加载)
[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缓存是如何工作的。
那么我做错了什么?
答案 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
应包含属性。