使用NHibernate和SQL Server地理位置的距离高级搜索
我在存储库中有一个现有的高级搜索方法,该方法检查FormCollection是否存在搜索条件,如果存在,则向搜索添加一个条件,例如使用NHibernate和SQL Server地理位置的距离高级搜索,nhibernate,sql-server-2008,geography,Nhibernate,Sql Server 2008,Geography,我在存储库中有一个现有的高级搜索方法,该方法检查FormCollection是否存在搜索条件,如果存在,则向搜索添加一个条件,例如 public IList<Residence> GetForAdvancedSearch(FormCollection collection) { var criteria = Session.CreateCriteria(typeof(Residence)) .SetResultTransformer(new DistinctRootEnt
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>();
}
存储库调用命名查询,因此:
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));
但是SpatialPression.IsWithinDistance返回了一个System.NotImplementedException。您看到了吗?这可能为您的问题提供一个简单的解决方案
另一种方法是创建自己的ICriterion实现——如果您是从AbstractCriterian派生的,并且以特定的数据库平台为目标,那么这并不太棘手。这将允许您将距离函数与其他条件相结合。创建一个投影,该投影实际上会在结果中添加一个新的距离列,该距离列由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));
更新
n、 虽然这在我发布它的时候一定有用,但它不再有用了。NHibernate不喜欢dbo后面的“.”,他说
无法解析属性:dbo of:Residences.Domain.Residence
如果我删除“dbo”,我会
“GetDistance”不是可识别的内置函数名
谢谢约翰,我一直在用它,但一直没能用起来。IsWithinDistance似乎没有得到实施。我试试你的第二个建议。
criteria.Add(SpatialExpression.IsWithinDistance(
"Coordinate", new Coordinate(latitude, longitude), 10));
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));