4

我正在尝试使用Query<T>()QueryOver<T>(). 使用 LINQ 查询时,我可以使用自定义的DefaultLinqToHqlGeneratorsRegistry. 这对于从表达式计算的属性非常有用,因此不会重复代码。

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

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

从我通过源代码看到的内容来看,QueryOver API 使用 Criterion 作为其基础......它直接转换为原始 SQL 而不是 HQL。

4

2 回答 2

3

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

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

对于标准,有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();
于 2013-05-06T11:15:56.113 回答
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();
于 2013-05-15T16:40:33.623 回答