我遇到了一些非常奇怪的行为,NHibernate 查询开始挂起。我制作了一个演示项目,以可重复的方式展示了这种行为。
你可以在这里下载项目
这是有问题的代码:
public IList<Post> GetLatestLiveBlogEntries(int numEntriesToRetrieve)
{
var maxDate = DateTime.Now;
using (var session = SessionManager.OpenSession())
{
var crit = session.CreateCriteria(typeof (Post))
.Add(Restrictions.Eq("Enabled", true))
.Add(Restrictions.Lt("postDate", maxDate))
.AddOrder(new Order("postDate", false))
//.SetFetchMode("author", FetchMode.Eager) // <-- the exclusion of this line breaks everything!
.SetMaxResults(numEntriesToRetrieve);
StupidFileLogger.Log("If this is the last log, I'm hanging on crit.List<Post>()");
var listOfPosts = crit.List<Post>();
StupidFileLogger.Log("I actually was able to retrieve the posts");
return listOfPosts;
}
}
关键行是作者字段上的 .SetFetchMode。在我的演示项目的第一次加载时,它加载良好。当我点击刷新时,它挂起并且永远不会超过 crit.List() 调用。通过急切的加载,它每次都能正常工作。
我正在使用 Castle.Facilities.NHibernateIntegration.Components.SessionWebModule 来确保每个请求 1 个会话。
我发现的另一件奇怪的事情是这只发生在 SQL Server 上。当我使用 SQLite 时,一切正常。在我的演示项目中,我有一个简单的构建标志,可让您轻松切换数据库。只需查看 /build 目录中的 local.properties.xml。
我知道在这种特殊情况下急切加载解决了我的问题,但在我的应用程序中,我不想急切加载所有内容。
请下载解决方案并自己尝试。我在其他机器上试过,他们做同样的事情。
以下是一些 SQL Profiler 捕获。您可以看到 Posts 的查询已发送到服务器,但它停在那里:
第一个请求(按预期运行):
好的请求 http://muc-central.com/misc/good_request.jpg
第二个请求(挂起):