NHibernate QueryOver按顺序进行算术运算

时间:2015-11-04 14:07:12

标签: c# nhibernate lambda queryover

我已经构建了一个HQL来使用CreateQuery查询某些实体,并且我尝试使用QueryOver将其转换为lambda表达式。

查询会在NegocioLatitude范围内查找Longitude,并按用户与Negocio之间的距离对其进行排序。我想将它转换为lambda表达式,因为它更容易维护,但我仍然按部分顺序排列。

这些是我拥有的实体。我已经省略了在这种情况下不相关的内容。

public class Negocio
{
   public Endereco Endereco {get; set;} 
}

public class Endereco
{
    public GeoCoordenada GeoCoordenada {get; set;}
}
public class GeoCoordenada
{
   public double Latitude {get; set;}
   public double Longitude {get; set;}
}

这是执行魔术的查询:

query = _session.CreateQuery(@"select distinct(n),
 SQRT(SQUARE(e.GeoCoordenada.Latitude - :lat) + SQUARE(e.GeoCoordenada.Longitude - :lon)) 
             from Negocio n inner join n.Endereco as e where 
             (e.GeoCoordenada.Latitude between (:minLat) and (:maxLat)) and 
             (e.GeoCoordenada.Longitude between (:minLon) and (:maxLon))
             order by SQRT(SQUARE(e.GeoCoordenada.Latitude - :lat) + 
             SQUARE(e.GeoCoordenada.Longitude - :lon))");`

        query.SetParameter("minLat", -90);  // random values just  
        query.SetParameter("maxLat", 90);   // for testing
        query.SetParameter("minLon", -180); 
        query.SetParameter("maxLon", 180);
        query.SetParameter("lat", 25);
        query.SetParameter("lon", 25);

这就是我现在所做的:

 var query = _session.QueryOver<Negocio>()
                .JoinQueryOver(x => x.Endereco)
                .WhereRestrictionOn(x => x.GeoCoordenada.Latitude).IsBetween(-90).And(90)
                .AndRestrictionOn(x => x.GeoCoordenada.Longitude).IsBetween(-180).And(180)

重要提示:我无法在调用List()后对其进行排序,因为在skip()take()的查询末尾会添加分页功能所以,一次查询所有结果毫无意义

关于如何实现这种排序的任何想法?

1 个答案:

答案 0 :(得分:0)

您可以使用ArithmeticOperatorProjection,这是为NHibernate编写的小扩展程序:http://savale.blogspot.ru/2011/04/nhibernate-and-missing.html

您的查询将如下所示:

_session.QueryOver<Negocio>()
    .JoinQueryOver(x => x.Endereco)
    .JoinQueryOver(x => x.GeoCoordenada)
    .WhereRestrictionOn(x => x.Latitude).IsBetween(-90).And(90)
    .AndRestrictionOn(x => x.Longitude).IsBetween(-180).And(180)
    .OrderBy(
        new ArithmeticOperatorProjection(
            "+",
            NHibernateUtil.Decimal,
            new ArithmeticOperatorProjection(
                "*",
                NHibernateUtil.Decimal,
                new ArithmeticOperatorProjection("-", NHibernateUtil.Decimal, Projections.Property<GeoCoordenada>(x => x.Longitude), Projections.Constant(25m)),
                new ArithmeticOperatorProjection("-", NHibernateUtil.Decimal, Projections.Property<GeoCoordenada>(x => x.Longitude), Projections.Constant(25m))
            ),
            new ArithmeticOperatorProjection(
                "*",
                NHibernateUtil.Decimal,
                new ArithmeticOperatorProjection("-", NHibernateUtil.Decimal, Projections.Property<GeoCoordenada>(x => x.Latitude), Projections.Constant(25m)),
                new ArithmeticOperatorProjection("-", NHibernateUtil.Decimal, Projections.Property<GeoCoordenada>(x => x.Latitude), Projections.Constant(25m))
            )
    )
    .List();

可以通过添加自定义SQRTSQUARE投影来进一步改善这一点。