是否存在查询生成器或QueryOver的扩展点,就像LINQ一样?

时间:2013-05-01 13:16:54

标签: .net linq nhibernate

我正在尝试使用我在Query<T>()内使用QueryOver<T>()的计算属性。使用LINQ查询时,我可以使用自定义DefaultLinqToHqlGeneratorsRegistry注册自定义生成器。这适用于calculated properties from an expression,因此代码不会重复。

我似乎无法找到为QueryOver API注册自定义生成器的扩展点。它存在吗?

我想必须在原始SQL字符串(Map(x => x.Prop).Formula("query").LazyLoad().Access.ReadOnly())内复制计算出的属性逻辑。这意味着逻辑的两倍和测试次数的两倍。

从我通过source看到的情况,QueryOver API使用Criterion作为其基础...它直接转换为原始SQL而不是HQL。

2 个答案:

答案 0 :(得分:3)

Linq和QueryOver采用不同的路径到sql:

QueryOver -> Expression -> Criteria \
Linq      -> LinqParser -> Hql      --> Sql

对于Criteria,NHibernate.Impl.ExpressionProcessor.RegisterCustomMethodCall(...);可能是你想要的。

一个简单的例子:

public static class QueryOverExtensions
{
    public static void Register()
    {
        ExpressionProcessor.RegisterCustomProjection(() => QueryOverExtensions.Day(default(DateTime)), QueryOverExtensions.ProcessDay);
        ExpressionProcessor.RegisterCustomProjection(() => QueryOverExtensions.Month(default(DateTime)), QueryOverExtensions.ProcessMonth);
        ExpressionProcessor.RegisterCustomProjection(() => QueryOverExtensions.Year(default(DateTime)), QueryOverExtensions.ProcessYear);
    }

    public static Int32 Day(this DateTime dateTimeProperty)
    {
        return (dateTimeProperty.Day);
    }

    public static Int32 Month(this DateTime dateTimeProperty)
    {
        return (dateTimeProperty.Month);
    }

    public static Int32 Year(this DateTime dateTimeProperty)
    {
        return (dateTimeProperty.Year);
    }

    private static IProjection ProcessDay(MethodCallExpression methodCallExpression)
    {
        IProjection property = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]).AsProjection();
        return (Projections.SqlFunction("day", NHibernateUtil.Int32, property));
    }

    private static IProjection ProcessMonth(MethodCallExpression methodCallExpression)
    {
        IProjection property = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]).AsProjection();
        return (Projections.SqlFunction("month", NHibernateUtil.Int32, property));
    }

    private static IProjection ProcessYear(MethodCallExpression methodCallExpression)
    {
        IProjection property = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]).AsProjection();
        return (Projections.SqlFunction("year", NHibernateUtil.Int32, property));
    }
}

别忘了拨打Register()。之后你可以像这样使用它:

session.QueryOver<Order>().Where(o => o.Date.Month() == DateTime.Today.Month).List();

答案 1 :(得分:0)

一个简单的例子:

public static class QueryOverExtensions
{
    public static void Register()
    {
        ExpressionProcessor.RegisterCustomProjection(() => QueryOverExtensions.Day(default(DateTime)), QueryOverExtensions.ProcessDay);
        ExpressionProcessor.RegisterCustomProjection(() => QueryOverExtensions.Month(default(DateTime)), QueryOverExtensions.ProcessMonth);
        ExpressionProcessor.RegisterCustomProjection(() => QueryOverExtensions.Year(default(DateTime)), QueryOverExtensions.ProcessYear);
    }

    public static Int32 Day(this DateTime dateTimeProperty)
    {
        return (dateTimeProperty.Day);
    }

    public static Int32 Month(this DateTime dateTimeProperty)
    {
        return (dateTimeProperty.Month);
    }

    public static Int32 Year(this DateTime dateTimeProperty)
    {
        return (dateTimeProperty.Year);
    }

    private static IProjection ProcessDay(MethodCallExpression methodCallExpression)
    {
        IProjection property = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]).AsProjection();
        return (Projections.SqlFunction("day", NHibernateUtil.Int32, property));
    }

    private static IProjection ProcessMonth(MethodCallExpression methodCallExpression)
    {
        IProjection property = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]).AsProjection();
        return (Projections.SqlFunction("month", NHibernateUtil.Int32, property));
    }

    private static IProjection ProcessYear(MethodCallExpression methodCallExpression)
    {
        IProjection property = ExpressionProcessor.FindMemberProjection(methodCallExpression.Arguments[0]).AsProjection();
        return (Projections.SqlFunction("year", NHibernateUtil.Int32, property));
    }
}

不要忘记拨打Register()。之后你可以像这样使用它:

session.QueryOver<Order>().Where(o => o.Date.Month() == DateTime.Today.Month).List();