c# - .NET Core - IEnumerable 与 IQueryable 产生不同的空间/地理结果
问题描述
我们将 ASP.NET Core 5 后端与 SQL Server v15 和 Entity Framework V5 一起使用,我一直在努力解决一些有趣的问题,考虑一下:
你有一个如下表:
CREATE TABLE [dbo].[ContactDetails](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](128) NOT NULL,
...
[Geolocation] [geography] NULL
)
该表被其他表使用,例如。Stores., 存储联系方式。
然后表 ContactDetails 会自动搭建,如下所示:
public partial class ContactDetail
{
public ContactDetail()
{
Stores = new HashSet<Store>();
}
public int Id { get; set; }
public string Name { get; set; }
public Geometry Geolocation { get; set; }
}
然后你从输入中存储商店的经度和纬度(双精度)让我们说:
Geometry Store.ContactDetails.Geolocation = new NetTopologySuite.Geometries.Point(store.longitude, store.latitude) { SRID = 4326 };
现在给定用户的位置,该位置以相同的方式创建
Geometry userLocation = new NetTopologySuite.Geometries.Point(user.longitude, user.latitude) { SRID = 4326 };
您想知道每个商店离用户有多远。你会怎么做?
我这样做了:
DbContext dbContext; //...somehow constructed
var dbSet = dbContext.Set<Store>();
var distances = dbSet.Where(...).Select(store => store.ContactDetails.Geolocation.Distance(userLocation));
但令我惊讶的是,距离完全消失了!我希望距离以度为单位返回,我将不得不将其转换为公里。但这些数字完全不存在(如 83130)。
所以我尝试了这个:
var anotherDistances = dbSet.Where(...).AsEnumerable().Select(store => store.ContactDetails.Geolocation.Distance(userLocation));
而这一次的距离与预期一致(例如 1.245 度)。
那里发生了什么?我需要保留结果,IQueryable
以便可以有效地进行进一步的过滤和转换。如何获得正确的距离而无需转换IQueryable
为IEnumerable
?
我无法从其他问题中找到答案,我怀疑 Linq 无法正确地将查询转换为 SQL,并且AsEnumerable()
在将对象加载到内存中时,之后的查询能够使用正确的类型推断并使用空间正确的方法。但这只是一些模糊的理解。如果您能帮助我理解这一点,我将不胜感激。
解决方案
啊好吧,谜团解开了。感谢 Dominik 的@dominik-berse 建议,我进一步挖掘。
当查询从 LINQ 转换为 SQL 时,被映射的函数不必是等价的。在这种情况下,NetTopologySuite.Geometries.Distance() 被转换为 geography::STDistance() - 这取决于 SRID 模型的类型,以不同的单位返回距离,如果是 4326 模型(由 GPS 使用),它是米。
当查询转换为对象时,直接调用对象的方法,在本例中为 NetTopologySuite.Geometries.Distance()。
而且这两个值可以完全不同。
推荐阅读
- javascript - 如何在输入框中添加单个字母过滤器
- python - 将 csv 下载到本地时出现 Unicode 解码问题
- awk - 通过 grep/awk/cut 删除字符串中的多余点
- swift - 从左下角动画`CATextLayer`字体大小
- wordpress - WordPress | 未登录时不可见更改
- react-native - React-Native:使用自定义 TextInput 组件添加文本限制指示器
- php - 将 HTMl 块添加到静态页面的表单
- database - 票号的架构,如 jira
- android - InverseBindingAdapter 不起作用,出现错误:
预期在生成的 Java 代码中 - javascript - Standardjs 忽略 .eslintrc 文件