无法让简单的实体框架空间查询工作
Posted
技术标签:
【中文标题】无法让简单的实体框架空间查询工作【英文标题】:Can't get a simple Entity Framework spatial query to work 【发布时间】:2014-12-02 15:31:18 【问题描述】:我的 sql 服务器上的这个查询返回很多行:
declare @referencepoint Geography = Geography::Point(48.208173, 16.373813, 4326);
SELECT *
FROM myTable
WHERE Location.STDistance(@referencepoint) < 20000
但 EF 中的等效项没有返回:
DbGeography referencepoint = DbGeography.PointFromText("POINT(48.208173 16.373813)", 4326);
var records = (from r in db.myTable
where r.Location.Distance(referencepoint ) <= 20000
select r).ToList();
查看通过分析器生成的查询,我看到了:
declare @p3 sys.geography
set @p3=convert(sys.geography,0xE6100000010CD4D17135B25F30408274B169A51A4840)
SELECT *
FROM [myTable]
WHERE ([Location].STDistance(@p3)) <= 20000
EF 有问题吗,还是我有问题?
【问题讨论】:
看来 EF 确实有问题 - PointFromText 得到 lat & lon 反转。 ***.com/questions/16546598/… 或者,我应该说 PointFromText 使用的 WellKnownText 格式需要 Point(lon, lat) 而 TSQL 使用 Point(lat, lon)。也许不是错误,但肯定会令人困惑...... 【参考方案1】:OP 在这里有问题 :) SQL 和 EF 都按预期工作。 OP的说法不正确。
SQL 点语法:
declare @referencepoint Geography = Geography::Point(48.208173, 16.373813, 4326);
实际上相当于.Net:
DbGeography referencepoint = DbGeography.PointFromText("POINT(16.373813 48.208173)", 4326);
// Note the parameters are reversed from OP's statement
在 SQL 和 EF (.Net) 中,Geography 数据类型使用标准 WellKnownText 表示法在内部定义点和多边形以及其他结构。
在WellKnownText 格式中,点被指定为笛卡尔平面上的 POINT(X Y)。 - 注意没有逗号,值仅由空格分隔
当我们想将地球上的位置表示为笛卡尔平面上的一个点时,X 轴是赤道,Y 轴是在北极和南极之间运行的Meridian 线。
Longitute,顾名思义就是地球表面的东西方位(所以平行于赤道,X纵坐标)
Latitude,顾名思义就是地球表面的南北位置(垂直于赤道,Y纵坐标)
因此,要以 WellKnownText 格式将地球上的点表示为笛卡尔平面上的点,我们必须使用以下语法:
POINT(经度纬度)
使问题感到困惑的是,在大多数口头和书面形式中,我们按顺序引用纬度和经度,因此在 SQL 中,我们有一个辅助函数按该顺序获取参数,因为这样可以减少混淆.在某种程度上确实如此,因为参数命名得当。为了进一步解释这一点,我已经通过更正扩展了 OP 的声明
SQL
DECLARE @latitude float = 48.208173
DECLARE @longitude float = 16.373813
DECLARE @srid int = 4326
DECLARE @referencepoint Geography = Geography::Point(@latitude, @longitude, @srid);
SELECT *
FROM myTable
WHERE Location.STDistance(@referencepoint) < 20000
.Net
double latitude = 48.208173;
double longitude = 16.373813;
int srid = 4326;
DbGeography referencepoint = DbGeography.PointFromText($"POINT(longitude latitude)", srid);
var records = (from r in db.myTable
where r.Location.Distance(referencepoint) <= 20000
select r).ToList();
我什至找不到一个很好的参考来解释为什么我们通常提到纬度和经度(按此顺序)我怀疑这是基于 LatLon 更好地从舌头上滚下来的事实,或者因为首先发现/测量了纬度?
【讨论】:
以上是关于无法让简单的实体框架空间查询工作的主要内容,如果未能解决你的问题,请参考以下文章