使用NHibernate和SQL Server的地理距离高级搜索(Advanced search w

2019-09-28 17:40发布

我有在检查一个储存库现有先进的搜索方法FormCollection的搜索条件的存在,如果存在,增加了一个标准的搜索如

public IList<Residence> GetForAdvancedSearch(FormCollection collection)
{
  var criteria = Session.CreateCriteria(typeof(Residence))
    .SetResultTransformer(new DistinctRootEntityResultTransformer());

  if (collection["MinBedrooms"] != null)
  {
    criteria
      .Add(Restrictions.Ge("Bedrooms", int.Parse(collection["MinBedrooms"])));
  }

  // ... many criteria omitted for brevity

  return criteria.List<Residence>();
}

我也有一个基本的距离搜索,找到每个住处有多远是从搜索标准中。 对于查询的HBM是

<sql-query name="Residence.Nearest">
  <return alias="residence" class="Residences.Domain.Residence, Residences"/>
  <return-scalar column="Distance" type="float"/>
  SELECT R.*, dbo.GetDistance(:point, R.Coordinate) AS Distance
  FROM Residence R
  WHERE Distance < 10
  ORDER BY Distance
</sql-query>

我必须定义一个函数来计算距离,因为没有办法让NHibernate的逃避地理功能冒号:

 CREATE FUNCTION dbo.GetDistance
 (
  @firstPoint nvarchar(100), 
  @secondPoint GEOMETRY
 )
 RETURNS float
 AS
 BEGIN
  RETURN GEOGRAPHY::STGeomFromText(
  @firstPoint, 4326).STDistance(@secondPoint.STAsText()) / 1609.344
 END

而库调用命名查询这样的:

return Session
   .GetNamedQuery("Residence.Nearest")
   .SetString("point", String.Format("POINT({0} {1})", latitude, longitude))
   .List();

所以我的问题是; 我该如何将二者结合起来(或从头开始),所以我可以过滤先进的搜索结果到10英里的搜索位置的内,只包括住宅?

更新我已经使用NHibernate.Spatial用下面的代码尝试:

criteria.Add(SpatialExpression.IsWithinDistance(
    "Coordinate", new Coordinate(latitude, longitude), 10));

SpatialExpression.IsWithinDistance返回System.NotImplementedException

Answer 1:

你见过NHibernate.Spatial项目 ? 这可以提供一个简单的解决您的问题。

另一种方法是创建自己的实现的ICriterion -如果从派生这是不是太棘手AbstractCriterion和您定位特定的数据库平台。 然后,这将允许您将距离函数与其他标准相结合。



Answer 2:

创建的投影的是,实际上,增加了一个新的距离列的结果,这是由称为UDF计算,然后添加限制给它:

var query = String.Format(
    "dbo.GetDistance('POINT({0} {1}', Coordinate) AS Distance", 
    latitude, longitude);
criteria
    .Add(Restrictions.Le(Projections.SqlProjection(
        query, 
        new [] {"Distance"}, 
        new [] {NHibernateUtil.Double}), 10));

UPDATE

注:虽然这一定工作时,我贴吧,这是行不通的了。 NHibernate的不喜欢“” DBO后,并说

“无法解析属性:DBO的:Residences.Domain.Residence”。

如果我删除“DBO”。 我得到

“‘getDistance的’是无法识别的内置函数名称。”



文章来源: Advanced search with distances using NHibernate and SQL Server Geography