2015-03-18 62 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());