我正在尝试使用我在 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。

最佳答案

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();

关于.net - QueryOver 是否有像 LINQ 一样的查询生成器或扩展点?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16318843/

10-11 16:19