gpt4 book ai didi

NHibernate - HQL "join fetch"与 SetMaxResults 引发错误

转载 作者:行者123 更新时间:2023-12-04 19:12:09 25 4
gpt4 key购买 nike

我正在尝试运行最简单的查询:

string queryStr = "select b " +
"from Blog b " +
"left outer join fetch b.BlogComments bc";

IList<Blog> blogs = Session.CreateQuery(queryStr)
.SetMaxResults(10)
.List<Blog>();

但它抛出以下错误:
System.ArgumentNullException: Value cannot be null.
Parameter name: source

但是,如果我从 HQL 中删除“提取”,它就可以正常工作。此外,如果我保留 fetch 但删除 SetMaxResults 它也可以正常工作。这与 fetch + SetMaxResults 组合有关。

我正在尝试急切加载子集合以优化查询并防止 SELECT N+1 问题。我将 NHibernate 3.3.1.4000 与 MySQL 数据库一起使用。

我的映射:
public class BlogMap : ClassMapping<Blog>
{
public BlogMap ()
{
// other properties (snip)....

Set(x => x.BlogComments, x =>
{
x.Inverse(true);
x.Cascade(Cascade.All | Cascade.DeleteOrphans);
x.Lazy(CollectionLazy.Extra);
x.Key(k => { k.Column("BlogId"); });
}, x => x.OneToMany());
}
}


public class BlogCommentMap : ClassMapping<BlogComment>
{
public BlogCommentMap ()
{
// other properties (snip)....

ManyToOne(x => x.Blog, x =>
{
x.Column("BlogId");
x.NotNullable(true);
});
}
}

根据要求进行堆栈跟踪:
[ArgumentNullException: Value cannot be null.
Parameter name: source]
System.Linq.Enumerable.ToList(IEnumerable`1 source) +4206743
NHibernate.Engine.QueryParameters.CreateCopyUsing(RowSelection selection) +178
NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters) +210
NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results) +369
NHibernate.Impl.SessionImpl.List(String query, QueryParameters queryParameters, IList results) +301

[GenericADOException: Could not execute query[SQL: SQL not available]]
NHibernate.Impl.SessionImpl.List(String query, QueryParameters queryParameters, IList results) +351
NHibernate.Impl.SessionImpl.List(String query, QueryParameters parameters) +282
NHibernate.Impl.QueryImpl.List() +162
WebApp.Repositories.BlogRepository.SearchBlogs(SearchBlogs search) in C:\...path...\BlogRepository.cs:43
WebApp.Controllers.HomepageController.Index(Int32 page) in C:\...path...\Controllers\HomepageController.cs:54
lambda_method(Closure , ControllerBase , Object[] ) +101
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +208
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +27
System.Web.Mvc.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12() +55
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +263
System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +19
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +191
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343
System.Web.Mvc.Controller.ExecuteCore() +116
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10
System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +37
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +50
System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8970061
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184

最佳答案

您遇到的是一个错误...但在这种情况下,它可能是 好兆头 ! ;) 因为对获取父级及其集合的查询进行分页( SetFirstResult()SetMaxResults() )将返回意外结果。让我们说,那

数据库 表格包含以下内容:

  • BlogA
    • BlogCommentA1
    • BlogCommentA2
    • BlogCommentA3
  • BlogB
    • BlogCommentB1
    • BlogCommentB2


QueryOver 语法(正在运行)与上述 HQL 相同:
var blogs = session.QueryOver<Blog>()
.Fetch(c => c.BlogComment).Eager // collection in one SQL
.Skip(0).Take(2) // paging, but weird...
.List<Blog>();

.Skip(0).Take(2) - 第一页,一个选择导致这两行但一个博客:

| BlogA | BlogCommentA1
| BlogA | BlogCommentA2



.Skip(2).Take(2) - 下一页,很奇怪……又是BlogA

| BlogA | BlogCommentA3
| BlogB | BlogCommentB1



而这很可能不是我们想要的。

建议:选择 SELECT 1+1

在这种情况下,最可靠的方法是仅在父对象 ( Blog ) 上进行分页。然后,当我们在 NHibernate session 中拥有所有博客( .Skip(2).Take(2) )时,我们只会为 调用一次 select全部 他们的 child ( BlogComments )。

最简单的方法是设置 batch-size="x" ,其中 x 是接近通常页面大小的数字(例如 25 或 50)。

.BatchSize(25)



NHibernate 文档 19.1.5. Using batch fetching解释细节

关于NHibernate - HQL "join fetch"与 SetMaxResults 引发错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13891628/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com