2015-03-18 108 views
1

与SQL方法扩展IQueryable的我用流利的NHibernate的,我需要从查询randomnize的结果,我想是这样的:NHibernate的,通过扩展DefaultLinqToHqlGeneratorsRegistry

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?

回答

1

现在的解决方案。

我不能让RandomOrder extention工作,但后来我读这: 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)

为了解决这个问题,我们需要绘制这个我们自己,所以我们可以忽略的参数,所以废除属性,并创建一个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());