【问题标题】:NHibernate 3 - extending Linq provider BaseHqlGeneratorForMethod.BuildHql problemNHibernate 3 - 扩展 Linq 提供程序 BaseHqlGeneratorForMethod.BuildHql 问题
【发布时间】:2011-05-31 06:31:33
【问题描述】:

我想用我自己的方法扩展 NHibernate 3 的默认 LINQ 提供程序。我希望能够使用我的 POCO 中的一些方法。我有一个名为 Range 的组件,它在我的许多 POCO 中经常使用。这个 nhibernate 组件类有一个方法 Contains(int value),我想在 LINQ 查询表达式中使用它

映射:

<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 类的 Min 和 Max 属性来构建 HqlTreeNode

【问题讨论】:

  • 你解决过这个问题吗?我也有同样的问题。
  • @BenCr,我从来没有解决这个问题 - 我只有 2 个地方可以使用这个 LINQ 扩展。对不起
  • 我将扩展方法更改为接受多个参数而不是对象的静态方法。它有效,但 NHibernate 3 LINQ 提供程序生成的 SQL 并不是特别理想,所以我现在放弃了它,转而使用 QueryOver api。这可能不如 LINQ sql 性能好,因此可能会被原始 HQL 取代。
  • @BenCr,当我尝试进行更复杂的查询时,命名 hql 查询是我现在最喜欢的了
  • 看起来像 answer to another question 在更新部分对其进行了整理。在其第一个版本(答案的开头)中,字段名称是硬编码的,在其第二个版本(答案的结尾)中,它是从实体属性解析的。

标签: linq nhibernate linq-to-nhibernate


【解决方案1】:
  1. 您可以使用手动方法:最简单的方法是创建一个表示您想要的 LINQ 树:arguments[0] &gt;= targetObject.Min &amp;&amp; arguments[1] &lt;= targetObject.Max。这里&gt;=Expression.GreaterThenOrEqual.Expression.Property等等。

    当您有一个表达式树时,只需将visitor 应用于它并返回它返回的内容(我不记得确切的 API,但如果需要其他帮助我可以查看它)。

  2. 另一个解决方案可能是尝试我的小库:Expressive
    它尝试将方法 IL 转换为表达式,因此您可以执行 LinqToHqlGeneratorsRegistryIRuntimeMethodHqlGenerator 来尝试内联任何未知属性/方法。

【讨论】:

    【解决方案2】:

    这里有一些扩展 LINQ 提供程序的好例子:http://www.primordialcode.com/

    【讨论】:

    • 你对这个问题有具体的答案吗,因为我在 6 个月后有一个类似的问题。我在那个网站上找到的例子都没有真正回答 OPs 的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多