覆盖NHibernate

时间:2016-10-18 20:07:40

标签: c# linq select nhibernate count

我正在使用NHibernate到Linq,我有一个已被过滤,排序和预测的可查询。 我正在使用第三方库来使用IQueryable,它处理分页并在其自己的扩展方法中计数 (Telerik Kendo MVC,QueryableExtensions.ToDataSourceResult(this IQueryable enumerable, DataSourceRequest request))。

我遇到的问题是在Count上(在ToDataSourceResult黑框中调用)。我收到异常QuerySyntaxException, "A recognition error occurred." Google搜索表明问题是在预计查询上调用count。 (Google groups post及相关StackOverflow post等)

NH在调用Count之前可以抛弃预测的建议导致我尝试通过使用BaseHqlGeneratorForMethodDefaultLinqToHqlGeneratorsRegistry扩展和注册新生成器来做到这一点。但我在网上找到的所有例子都是为了增加新的功能,而不是替换它。

有没有办法覆盖/替换Count方法NH句柄,以便我可以手动删除投影?

一个附带问题:是否有任何关于将NHibernate-to-Linq扩展的官方文档?我见过this

修改

这是我到目前为止所尝试的内容,而且我没有尝试新的扩展方法。我显然是新手......

public class InteumLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public InteumLinqToHqlGeneratorsRegistry()
        : base()
    {
        RegisterGenerator(ReflectionHelper.GetMethod(() => Queryable.Count<object>(null)), new NHibernateCountGenerator());
    }
}

public class NHibernateCountGenerator : BaseHqlGeneratorForMethod
{
    public NHibernateCountGenerator()
    {
        SupportedMethods = new[]
        { 
            ReflectionHelper.GetMethod(() => NHibernateCount.InteumCount<object>(null))
        };
    }

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
    {
        return treeBuilder.Count(visitor.Visit(arguments[0]).AsExpression());
    }
}

public static class NHibernateCount
{
    public static int InteumCount<T>(this IQueryable<T> query)
    {
        //  TODO: Remove projection from query

        return query.Count();
    }
}

编辑2 事实证明我错过了调用Kendo.Mvc.Extensions.Count(IQueryable)而不是Queryable.Count&lt;&gt;(IQueryable&lt;&gt;)的部分。做了一些改变,仍然,我没有击中HqlGenerator,虽然我仍然不确定它应该击中发电机......

1 个答案:

答案 0 :(得分:0)

我已经通过包装IQueryable解决了这种需求。毕竟它只是一个界面。

例如,在lambda项目中,Oracle与“select in”语句一起使用,限制为1000个值。我决定将ISession包装起来,以便为没有任何客户更改(非侵入性)的开发人员包装IQueryable。 在通过NHibernate进行IQueryable评估为IEnumerable之前,我将表达式替换为将所有Contains调用更改为“partition contains”:(。CONTins(...)&amp;&amp; .Contains(...)&amp;&amp; .Contains( ......)&amp;&amp; ...)。

在您的情况下,您可以对IQueryable评估执行相同的单值(IQueryable.Execute)。检测它是否为Count表达式...使用表达式visitor对表达式应用更改,最后将修改后的表达式的计算委托给NHibernate。