.NET – Queryover’s query generator or extension point is the same as Linq?

I’m trying to use the calculated properties used by Query< T>() inside QueryOver< T>(). When using LINQ queries, I can use the custom Default LinqToHqlGeneratorsRegistry to register the custom generation This applies to calculated properties from an expression, so the code will not be repeated.

I can’t seem to find an extension point to register a custom generator for the QueryOver API. Does it exist?

I don’t want to copy the calculated attribute logic in the original SQL string (Map(x => x.Prop).Formula(“query”).LazyLoad().Access.ReadOnly()). This means twice the logic and twice the number of tests.

From what I have seen in the source, the QueryOver API uses Criterion as its basis…It is directly converted to raw SQL instead of HQL .

Linq and QueryOver use different SQL paths:

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

For Criteria, there is NHibernate.Impl.ExpressionProcessor.RegisterCustomMethodCall(… ); This may be what you want.

A simple example:

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(d efault(DateTime)), QueryOverExtensions.ProcessYear);
}

public static Int32 Day(this DateTime dateTimeProperty)
{
return (dateTimeProperty.Day);< br /> }

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(m ethodCallExpression.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));
}
}

Don’t forget to call Register(). Then you can use it like this:

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

I’m trying to use the calculated properties used by Query() inside QueryOver(). When using LINQ query, I can register a custom generator with a custom Default LinqToHqlGeneratorsRegistry. This is for calculated properties from an expression, so the code won’t be repeated.

I can’t seem to find an extension point to register a custom generator for the QueryOver API. Does it exist?

I don’t want to copy the calculated attribute logic in the original SQL string (Map(x => x.Prop).Formula(“query”).LazyLoad().Access.ReadOnly()). This means twice the logic and twice the number of tests.

From what I have seen in the source, the QueryOver API uses Criterion as its basis…It is directly converted to raw SQL instead of HQL .

Linq and QueryOver use different sql paths:

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

For Criteria, there is NHibernate.Impl.ExpressionProcessor.RegisterCustomMethodCall(…); this may be what you want.

A simple example:

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)
{< br /> 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));
}
}< /pre>

Don’t forget to call Register(). Then you can use it like this:

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

Leave a Comment

Your email address will not be published.