我遇到问题,除非相关实体被缓存 它们被指定(映射中的Not.LazyLoad())。如果我建立一个查询 在Criteria或Linq中,主要实体被缓存,但没有关联 实体。
IList<NewsItem> news;
using (var session = factory.OpenSession())
{
Console.WriteLine("First Query");
news = session.CreateCriteria(typeof(NewsItem))
.SetCacheable(true)
.SetFetchMode("Author", FetchMode.Eager) // associated entity eager loaded
.List<NewsItem>();
}
foreach (var item in news)
{
Console.WriteLine("Author: " + item.Author.Name); //works fine first time
}
using (var session = factory.OpenSession())
{
Console.WriteLine("");
Console.WriteLine("Second Query");
news = session.CreateCriteria(typeof(NewsItem))
.SetCacheable(true)
.SetFetchMode("Author", FetchMode.Eager)
.List<NewsItem>();
}
foreach (var item in news)
{
Console.WriteLine("Author: " + item.Author.Name); //NHibernate.LazyInitializationException
}
我想避免通过映射急于加载关联 文件。其他人有类似的问题。
任何反馈意见。
答案 0 :(得分:0)
查询缓存(SetCacheable(true)
)的作用是存储查询检索到的 ID ;然后它逐个水合对象(希望来自实体缓存)。
IIRC,在缓存查询时,不使用相关entites的FetchModes,因此没有初始化Author引用。
值得注意的是,您不应该在会话之外使用您的实体,但这是一种解决方法:
news = session.CreateCriteria(typeof(NewsItem))
.SetCacheable(true)
.SetFetchMode("Author", FetchMode.Eager)
.List<NewsItem>();
foreach (var item in news)
{
var name = item.Author.Name;
}
这将强制初始化会话内的代理;那样你以后就可以使用它们了。
当然,您需要确保同时缓存NewsItem和Author,否则您实际上会通过缓存查询来降低性能。