我知道我的数据库包含一个包含这两个属性的帖子:
latitude: 44.611589
longitude: -122.215347
我正在编写一种方法来查找数据库中距离该位置50.0米范围内的所有帖子。 (因此,在这种情况下,由于有一个具有这些精确坐标的帖子,它的距离为0米,应该包括在内。)
这是我的代码:
DbGeography queryLocation = DbGeography.FromText("POINT(-122.215437 44.611589)", 4326);
double d = (double) DbGeography.FromText(
"POINT(-122.215347 44.611589)"
, 4326)
.Distance(queryLocation);
//d is equal to 0 when I execute this, as expected.
IQueryable<Post> posts = db.Posts.Where(p => (double) DbGeography.FromText(
"POINT(" + SqlFunctions.StringConvert(p.Longitude) + " " + SqlFunctions.StringConvert(p.Latitude) + ")"
, 4326).Distance(queryLocation) <= 50.0);
//posts is an empty collection when this executes.
为什么我的收藏是空的? LINQ查询在执行时应该看起来与double d
的代码完全相同,因为p.Longitude
和p.Latitude
将等于它们各自的值(它们肯定存在于数据库中,我对它们进行了硬编码在那里)。
编辑:
当我对查询中的值进行硬编码时,它可以工作:
var posts = db.Posts
.Where(p => (double) DbGeography.FromText(
"POINT(-122.215347 47.611589)"
, Constants.MetersCoordinateSystemId)
.Distance(queryLocation) <= 50.0);
这会正确返回具有正确纬度/经度值的帖子。所以我认为可以假设SqlFunctions.StringConvert()
不起作用,但我无法测试它,因为它似乎不能在LINQ表达式之外工作。此外,String.format和double.toString()在LINQ表达式中不起作用。
确认,它是SqlFunctions.StringConvert()
的问题var posts = db.Posts
.Where(p => (double) DbGeography.FromText(
"POINT(" + SqlFunctions.StringConvert(-122.215347) + " " + SqlFunctions.StringConvert(47.611589) + ")"
, Constants.MetersCoordinateSystemId)
.Distance(queryLocation) <= 50.0);
这也不起作用(返回空集合)。
编辑:这是我的LINQ查询生成的SQL:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[UserId] AS [UserId],
[Extent1].[Latitude] AS [Latitude],
[Extent1].[Longitude] AS [Longitude]
FROM [dbo].[Posts] AS [Extent1]
WHERE (geography::STGeomFromText(N'POINT(' + STR(cast(-122.215347 as float(53))) + N' ' + STR(cast(44.611589 as float(53))) + N')', 4326).STDistance(@p__linq__0)) <= cast(50 as float(53))
SQL不起作用,而STR(cast(...))
部分不起作用。当我用它替换它时它确实有用:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[UserId] AS [UserId],
[Extent1].[Latitude] AS [Latitude],
[Extent1].[Longitude] AS [Longitude]
FROM [dbo].[Posts] AS [Extent1]
WHERE (geography::STGeomFromText(N'POINT(' + LTRIM(Str(-122.215347, 25, 5))
+ N' ' + LTRIM(Str(44.611589, 25, 5)) + N')', 4326).STDistance(geography::STGeomFromText(N'POINT(-122.215347 47.611589)',4326)) <= 50)
从技术上讲,我可以编写自己的SQL。好极了。现在有没有办法通过LINQ to Entities做到这一点?
答案 0 :(得分:0)
尝试使用PointFromText而不是FromText:
DbGeography queryLocation = DbGeography.PointFromText("POINT(-122.215437 44.611589)", 4326);
double d = (double) DbGeography.PointFromText(
"POINT(-122.215347 44.611589)"
, 4326)
.Distance(queryLocation);
//d is equal to 0 when I execute this, as expected.
IQueryable<Post> posts = db.Posts.Where(p => (double) DbGeography.PointFromText(
"POINT(" + SqlFunctions.StringConvert(p.Longitude) + " " + SqlFunctions.StringConvert(p.Latitude) + ")"
, 4326).Distance(queryLocation) <= 50.0);