NHibernate 和 NHibernate LINQ:将 Fetch() 与自定义 ToPagedList 方法结合使用
我在将 nHibernate Fetch() (或 FetchMany())方法与我的分页方法一起使用时遇到问题,该方法使用 Futures 来获取所需的信息。我不知道如何解决它,但我确切地知道它在做什么。让我解释一下到目前为止我所掌握的情况。
public static IFutureValue<TResult> ToFutureValue<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<IQueryable<TSource>, TResult>> selector) where TResult : struct
{
var provider = (NhQueryProvider)source.Provider;
var method = ((MethodCallExpression)selector.Body).Method;
var expression = Expression.Call(null, method, source.Expression);
return (IFutureValue<TResult>)provider.ExecuteFuture(expression);
}
它工作得很好,使用它,我可以将获取行数和获取结果集结合到一个仅生成单个数据库命中的单分页方法中。我的分页方法如下所示。
public static IList<T> ToPagedList<T>(this IQueryable<T> query, int pageIndex, int pageSize, out int count)
{
var futureCount = query.ToFutureValue(x => x.Count());
var futureResults = pageIndex == 0 && pageSize == 0 ? query.ToFuture() : query.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToFuture();
count = futureCount.Value;
return futureResults.ToList();
}
有了这个,我就可以进行如下查询。
repositoryInstance.Query().Where(x=>x.SomeTextField.Contains("lake")).ToPagedList(pageIndex, pageSize, out count);
这就像一个魅力。然而现在我需要能够将某些关系定义为急切加载,在这种情况下它可能看起来像这样。
repositoryInstance.Query().Where(x=>x.SomeTextField.Contains("lake")).FetchMany(x=>x.Details).ToPagedList(pageIndex, pageSize, out count);
这会引发 QueryException,其描述为“查询指定了联接获取,但所获取关联的所有者不存在于选择列表中”。这样做的原因是因为我的分页方法,它试图对带有 Fetch() 的查询应用聚合行计数,但你不能这样做,因为错误是正确的。获取的关联的所有者不在选择列表中(至少不在其中一个列表中),我的选择本质上是针对第一个查询的单个整数。我想也许我可以在 ToPagedList 中删除一次用于任何提取的表达式节点,但我不知道这是否可能,也不知道它会有多难看。我正在寻找一些替代方案,可以让我们获得我想要的行为,同时绕过获取工作方式的限制。有什么想法吗?
I have a problem with using the nHibernate Fetch() (or FetchMany()) method with my paging method which uses Futures to get the information it needs. And I'm not sure how to fix it but I know exactly what it's doing. Let me explain what I have so far.
I'm using an extension method found here to let me get a row count as a Future value. it looks like this.
public static IFutureValue<TResult> ToFutureValue<TSource, TResult>(this IQueryable<TSource> source, Expression<Func<IQueryable<TSource>, TResult>> selector) where TResult : struct
{
var provider = (NhQueryProvider)source.Provider;
var method = ((MethodCallExpression)selector.Body).Method;
var expression = Expression.Call(null, method, source.Expression);
return (IFutureValue<TResult>)provider.ExecuteFuture(expression);
}
It works great, using this I can then combine getting a row count and getting my result set into a signle paging method that only generates a single database hit. My Paging method looks like this.
public static IList<T> ToPagedList<T>(this IQueryable<T> query, int pageIndex, int pageSize, out int count)
{
var futureCount = query.ToFutureValue(x => x.Count());
var futureResults = pageIndex == 0 && pageSize == 0 ? query.ToFuture() : query.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToFuture();
count = futureCount.Value;
return futureResults.ToList();
}
With this in place I can make queries like the following.
repositoryInstance.Query().Where(x=>x.SomeTextField.Contains("lake")).ToPagedList(pageIndex, pageSize, out count);
This much works like a charm. However now I need to be able to define certain relationships as eager loaded, in this case it might look like this.
repositoryInstance.Query().Where(x=>x.SomeTextField.Contains("lake")).FetchMany(x=>x.Details).ToPagedList(pageIndex, pageSize, out count);
This blows up with a QueryException with the description "Query specified join fetching, but the owner of the fetched association was not present in the select list". The reason for this is because of my paging method, it's trying to apply an aggregate row count on the query which has the Fetch() on it, and you can't do that, because the error is right. The owner of the fetched association wasn't in the select list (at least it isn't in one of them), my select is essentially for the first query is for a single integer. I thought maybe I could rip out the Expression nodes once in the ToPagedList that are for any fetching but I have no idea if it's possible or how ugly it would be. I'm looking for some alternatives that might let be get the behavior I want while bypassing the limitation on how Fetching works. Any thoughts?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以按如下方式修改 ToPagedList:
并像这样使用它:
我知道它稍微不太优雅,但它会起作用,并且比修改现有表达式更容易。
You could modify ToPagedList as follows:
And use it like this:
I know it's slightly less elegant, but it will work, and it's way easier than modifying an existing expression.