【问题标题】:IsWithinDistance could not be translatedIsWithinDistance 无法翻译
【发布时间】:2020-12-09 21:15:56
【问题描述】:

我正在尝试返回给定位置 50 英里范围内的项目列表。

我的表(简体)如下:

  • 身份证
  • 经度
  • 纬度
  • 状态
  • 活动

我有一个初始查询:

var query = db.MyTable.Where(o=> o.Status == "New" && o.Active == true);

query = query.Where(o => new Point(o.Longitude, o.Latitude)
                  .IsWithinDistance(new Point(_currentLongitude, _currentLatitude), 50));

var result = query.ToList()

但是 - 它似乎不起作用并且出现如下错误 - 任何想法如何解决这个问题?或者是否有更好的方法来获取最近的物品?

.Where(p => 新点(p.Longitude, p.Latitude) .IsWithinDistance(geom: __p_3,
距离:___maxDistance_4))' 无法翻译。

要么以可翻译的形式重写查询,要么通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用显式切换到客户端评估。请参阅https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。

Startup.cs:

services.AddDbContext<AppDbContext>(options =>
{
                
 options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
   x => x.UseNetTopologySuite());
});

【问题讨论】:

  • 您需要完全按照错误消息的建议进行操作:“要么以可翻译的形式重写查询,要么通过插入对 AsEnumerable() 的调用显式切换到客户端评估、AsAsyncEnumerable()、ToList() 或 ToListAsync()。有关详细信息,请参阅 go.microsoft.com/fwlink/?linkid=2101038"
  • @RobertHarvey - 这是Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite 中的内置函数。见EF Core Spatial DataSpatial Data in the SQL Server EF Core Provider
  • @Steve - 你添加了.UseNetTopologySuite as shown here 吗? (另外,我假设是SQL Server,请确认或更正。)
  • @MattJohnson-Pint: TIL
  • 据我所知,目前不支持从纬度/经度创建新的Point。您可能需要在模型上将数据存储为 Point 类型。

标签: c# .net-core entity-framework-core spatial-query nettopologysuite


【解决方案1】:

要使此功能发挥作用,您需要将这些坐标存储为 SQL geography 字段中的 Point。您可以轻松地将其作为新属性的计算列添加到现有模型中。

// on your entity
public Point Coordinates { get; }

// in your db context's OnModelCreating
  modelBuilder.Entity<YourEntity>()
    .Property(x => x.Coordinates)
    .IsRequired()
    .HasComputedColumnSql("geography::Point(Latitude, Longitude, 4326)");

注意,SRID 4326 是 SQL Server 支持的常用纬度/经度坐标系。 More on that here.

构建您的模型并部署到您的数据库。

现在你有了空间字段和属性,你可以这样查询:

var point = new Point(_currentLongitude, _currentLatitude) { SRID = 4326 };
var distanceInMeters = 50 * 1609.344;  // 50 miles to meters conversion
var results = db.YourEntity
                .Where(x => x.Coordinates.IsWithinDistance(point, distanceInMeters))
                .ToList();

SRID 4326 使用 表示距离,因此如果您使用英里,请务必按上面所示进行转换。

此外,如果您有大量数据,您还需要在该列上添加空间索引,但 EF Core doesn't support that directly yet 所以您必须直接在 SQL 中执行此操作。

【讨论】:

  • 注意,计算列方法是可选的。你总是可以只拥有一个 Point 属性,但你不会有单独的纬度/经度属性。
  • 您好,感谢您的快速回复,我会尝试一下。拥有/不拥有 Point 的计算列有什么好处吗?
  • Point (sql geography) 字段是进行空间查询工作的必要数据。您可以只填充 Point 并关闭单独的纬度/经度字段。两者兼有主要是为了方便。
  • @MattJohnson-Pint 请你看看这个stackoverflow.com/questions/70847958/…
猜你喜欢
  • 2021-06-26
  • 2014-07-14
  • 2022-10-20
  • 2021-04-13
  • 2021-06-23
  • 2020-10-26
  • 1970-01-01
  • 2018-05-13
  • 2020-05-08
相关资源
最近更新 更多