2010-10-12 2 views
4

Я хочу расширить LINQ-провайдер по умолчанию для NHibernate 3 с помощью своих собственных. Я хочу использовать некоторые методы из своих POCOs. У меня есть компонент Range, который используется довольно часто во многих моих POCOs. Этот NHibernate класс компонент метод содержит (целое значение), которое я хочу использовать в LINQ запроса выраженийNHibernate 3 - расширяющий поставщик Linq BaseHqlGeneratorForMethod.BuildHql проблема

Mapping:

<class name="Foo"> 
    ... 
    <component name="AgeRange"> 
    <property name="Min" column="age_min" /> 
    <property name="Max" column="age_max" /> 
    </component> 
</class> 

Класс

public class Range { 
    public int Min { get; set; } 
    public int Max { get; set; } 

    public bool Contains(int value) { 
    return value >= this.Min && value <= this.Max; 
    } 
} 

// this is the LINQ query I want to be able to write 
// which will generate 'SELECT * FROM Foo WHERE 25 BETWEEN age_min AND age_max' 
var s = from x in session.Query<Foo> where x.AgeRange.Contains(25) select x; 

// I know the following works 
var s = from x in session.Query<Foo> where x.AgeRange.Min <= 25 && x.AgeRange.Max >= 25 select x; 

Я посмотрел на несколько постов в блоге объясняя, как для расширения LINQ-провайдера, но я не знаю, как создавать выражения, необходимые для этого.

public class RangeContainsGenerator : BaseHqlGeneratorForMethod 
{ 
    public MemberInfo RangeMin; 
    public MemberInfo RangeMax; 

    public RangeContainsGenerator() { 
     SupportedMethods = new[] { 
      ReflectionHelper.GetMethodDefinition<Range>(x=> x.Contains(0)), 
     }; 

     RangeMin = ReflectionHelper.GetProperty<Range, int>(x => x.Min); 
     RangeMax = ReflectionHelper.GetProperty<Range, int>(x => x.Max); 
    } 

    public override NHibernate.Hql.Ast.HqlTreeNode BuildHql(
     System.Reflection.MethodInfo method, 
     System.Linq.Expressions.Expression targetObject, 
     System.Collections.ObjectModel.ReadOnlyCollection<System.Linq.Expressions.Expression> arguments, 
     NHibernate.Hql.Ast.HqlTreeBuilder treeBuilder, 
     NHibernate.Linq.Visitors.IHqlExpressionVisitor visitor) { 
      // The targetObject parameter contains the "Foo.AgeRange" member access expression 
      throw new NotImplementedException(); 
    } 
} 

В методе BuildHql я не знаю, как получить доступ к минимальному и максимальному свойства моего класса Range, чтобы построить HqlTreeNode

+0

Вы когда-нибудь получали это? У меня такая же проблема. – BenCr

+0

@BenCr, я так и не получил это - у меня было только 2 места, где я бы использовал это расширение для LINQ. Извините – Vasea

+0

Я изменил свой метод расширения на статический метод, который принимает несколько параметров вместо объекта. Это сработало, но SQL, который генерирует поставщик NHibernate 3 LINQ, не является особенно оптимальным, поэтому я отказался от него в пользу QueryOver api на данный момент. Это, вероятно, менее реалистично, чем LINQ sql, поэтому, вероятно, будет заменен необработанным HQL. – BenCr

ответ

2
  1. Вы можете использовать ручной подход: самым простым способом является создание дерева LINQ, представляющего то, что вы хотите: arguments[0] >= targetObject.Min && arguments[1] <= targetObject.Max. Здесь >= - Expression.GreaterThenOrEqual, . - Expression.Property и так далее.

    Если у вас есть дерево выражений, просто примените к нему visitor и верните то, что он возвращает (я не помню точный API, но я могу изучить его, если нужна дополнительная помощь).

  2. Другим решением может быть попытка использовать мою небольшую библиотеку: Expressive.
    Он пытается преобразовать метод IL в выражения, так что вы можете сделать LinqToHqlGeneratorsRegistry или IRuntimeMethodHqlGenerator, который пытается ввести любое неизвестное свойство/метод.

+0

спасибо, что очень помогло – Vasea

1

Есть несколько хороших примеров расширения поставщика LINQ здесь: http://www.primordialcode.com/

+0

У вас есть конкретный ответ на этот вопрос, так как у меня есть знакомый вопрос сейчас через 6 месяцев. Ни один из примеров, которые я мог найти на этом сайте, не ответил на вопрос OPs. – BenCr

Смежные вопросы