1

我在存储库中有一个现有的高级搜索方法,用于检查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 转义 geography 函数中的冒号:

 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.

4

2 回答 2

0

你见过NHibernate.Spatial 项目吗?这可能会为您的问题提供简单的解决方案。

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

于 2009-12-02T23:37:16.120 回答
0

创建一个投影,它实际上向结果中添加了一个新的距离列,该列通过称为 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));

更新

nb 虽然这在我发布它时一定有效,但它不再有效。NHibernate 不喜欢 '.' 在dbo之后,说

“无法解析属性:dbo of:Residences.Domain.Residence”。

如果我删除“dbo”。我明白了

“'GetDistance' 不是可识别的内置函数名称。”

于 2009-12-03T13:50:08.627 回答