【问题标题】:NHibernate, extend IQueryable with SQL method by extending DefaultLinqToHqlGeneratorsRegistryNHibernate,通过扩展 DefaultLinqToHqlGeneratorsRegistry 使用 SQL 方法扩展 IQueryable
【发布时间】:2016-02-02 01:30:25
【问题描述】:

我使用流利的 NHibernate,我需要随机化查询的结果,我想要的是这样的:

select * from table order by newid()

方法,应该是扩展 NHibernate IQueryable 生成器以使用像 QueryableExtension.RandomOrder<T>(this IQueryable<T> list) 这样的方法

这里的博客:http://fabiomaulo.blogspot.dk/2010/07/nhibernate-linq-provider-extension.html 还有这个:Extending LINQ to Nhibernate provider, in combination with Dynamic LINQ problem

我写了这段代码:

public class RandomOrderGenerator : BaseHqlGeneratorForMethod
{
    public RandomOrderGenerator()
    {
        SupportedMethods = new[]
        {
            ReflectionHelper.GetMethod(() => Enumerable.Empty<object>().AsQueryable().RandomOrder()),
            ReflectionHelper.GetMethod(() => Enumerable.Empty<long>().AsQueryable().RandomOrder()),
        };
    }

    public override HqlTreeNode BuildHql(MethodInfo method, System.Linq.Expressions.Expression targetObject, ReadOnlyCollection<System.Linq.Expressions.Expression> arguments,
        HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
    {
        throw new NotImplementedException();
    }
}

public class MyLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public MyLinqToHqlGeneratorsRegistry()
    {
        RegisterGenerator(ReflectionHelper.GetMethod(() => Enumerable.Empty<object>().AsQueryable().RandomOrder()), new RandomOrderGenerator());
    }
}

我已配置为使用MyLinqToHqlGeneratorsRegistry,它被创建,我的RandomOrderGenerator 被创建,但BuildHql 方法从未被调用。

扩展的使用:

repository.Query<Table>().Take(10).RandomOrder().Select(x => x.Id);

SupportMethodsRegisterGenerator 方法定义应该是一样的,但是为什么我不能让它生成 HQL?

【问题讨论】:

    标签: c# linq nhibernate fluent-nhibernate extension-methods


    【解决方案1】:

    现在有了解决方案。

    我无法让 RandomOrder 扩展工作,但后来我读到了这个: https://nhibernate.jira.com/browse/NH-3386

    这里有 LinqExtensionMethod,它会在 sql 中自动调用该方法。这里的问题是,当表达式不依赖于数据库中的任何特定内容时,它会在本地编译,为此传递数据库特定于方法的内容。

    repository.Query<Table>().Take(10).OrderBy(x => OrderType.Random(x.Id))...
    

    LinqExtensionMethods 由DefaultLinqToHqlGeneratorsRegistry 处理,并将参数映射到 SQL 方法,非常简洁,但不是我们想要的。现在 sql 看起来像这样: select....newid(table.id)

    要解决这个问题,我们需要自己映射它,这样我们就可以忽略参数,所以不用 Attribute 并创建一个 hql 生成器:

    public class RandomOrderHqlGenerator : BaseHqlGeneratorForMethod
    {
        private readonly string _name;
        public RandomOrderHqlGenerator()
        {
            _name = "NewId";
        }
        public override HqlTreeNode BuildHql(MethodInfo method, System.Linq.Expressions.Expression targetObject, ReadOnlyCollection<System.Linq.Expressions.Expression> arguments,
            HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
        {
            return treeBuilder.MethodCall(_name);
        }
    }
    

    RegisterGenerator(ReflectionHelper.GetMethodDefinition(() =&gt; OrderType.Random(null)), new RandomOrderHqlGenerator());

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多