使用 NHibernate 和 SQL Server Geography 进行高级距离搜索
我在存储库中有一个现有的高级搜索方法,它检查 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
。
I've got an existing advanced search method in a repository that checks a FormCollection
for the existence of search criteria, and if present, adds a criterion to the search e.g.
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>();
}
I've also got a basic distance search to find how far each residence is from the search criteria. The HBM for the query is
<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>
I had to define a function to calculate the distance, as there was no way to get NHibernate to escape the colons in the geography function:
CREATE FUNCTION dbo.GetDistance
(
@firstPoint nvarchar(100),
@secondPoint GEOMETRY
)
RETURNS float
AS
BEGIN
RETURN GEOGRAPHY::STGeomFromText(
@firstPoint, 4326).STDistance(@secondPoint.STAsText()) / 1609.344
END
And the repository calls the named query thus:
return Session
.GetNamedQuery("Residence.Nearest")
.SetString("point", String.Format("POINT({0} {1})", latitude, longitude))
.List();
So my question is; how do I combine the two (or start from scratch), so I can filter the advanced search results to include only residences within 10 miles of the search location?
UPDATE I have tried using NHibernate.Spatial with the following code:
criteria.Add(SpatialExpression.IsWithinDistance(
"Coordinate", new Coordinate(latitude, longitude), 10));
but SpatialExpression.IsWithinDistance
returned a System.NotImplementedException
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您看过NHibernate.Spatial 项目吗?这可能会为您的问题提供一个简单的解决方案。
另一种方法是创建您自己的
ICriterion
实现 - 如果您从AbstractCriterion
派生并且面向特定的数据库平台,那么这并不太棘手。这将允许您将距离函数与其他标准结合起来。Have you seen the NHibernate.Spatial project? This may provide an easy solution to your problem.
The alternative is to create your own implementation of
ICriterion
- this is not too tricky if you derive fromAbstractCriterion
and you target your particular database platform. This would then allow you to combine your distance function with other criteria.创建一个投影,实际上将一个新的距离列添加到结果中,该距离列是通过称为 UDF 计算的,然后向其添加限制:
更新
nb 虽然这在我发布时必须有效它,它不再起作用了。 NHibernate 不喜欢“.”在 dbo 之后,并说
如果我删除“dbo”。我明白了
Create a projection that, in effect, adds a new distance column to the results, which is calculated by called the UDF, and then add a restriction to it:
UPDATE
n.b. Although this must have worked when I posted it, it doesn't work any more. NHibernate doesn't like the '.' after dbo, and says
If I remove the 'dbo.' I get