我使用流畅的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);
SupportMethods
和RegisterGenerator
方法定义应该相同,但为什么我不能让它生成HQL?
答案 0 :(得分: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(() => OrderType.Random(null)), new RandomOrderHqlGenerator());