You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 6 EF Core中SQL Server Geography类型支持问题咨询

问题描述

我有一个.NET Core 6应用程序和SQL Server数据库,其中某表包含类型为Geography的列。我的目标是用LINQ查询获取距离指定点小于40000米的行列表。现有可正常执行的T-SQL语句如下:

-- SPATIAL WITHIN DISTANCE
DECLARE @Origin GEOGRAPHY,
        -- 距离单位为米
        @Distance INTEGER = 40000;        

-- 中心点
SET @Origin = GEOGRAPHY::STGeomFromText('POINT(-93.5663 44.9033)', 4326);

-- 返回40公里范围内的所有行
SELECT * FROM dbo.GeographyAreas WHERE @Origin.STDistance(Geography) <= @Distance;

我更倾向于在应用数据层用LINQ语法实现,而非存储过程,但遇到了SQL Server Geography列类型与空间库的匹配问题:

  • NetTopologySuite支持Geometry类型,但似乎不支持Geography;
  • Microsoft.Spatial的Geography类型无法映射到SQL Server的Geography类型;
  • Microsoft.SqlServer.Types适用于传统.NET,而非.NET Core。

我期望实现类似如下的代码:

public class GeographyAreas
{
   public <SomeGeographyType> Geography { get; set; }
}

var origin = <SomeGeographyType>(-93.123, 44.456);
var dist = 40000;

List<GeographyAreas> results = _context.GeographyAreas.Where(x => x.Geography.Distance(origin) < dist).ToList();

但执行时出现错误:

The Geography property of GeographicAreas.Geography could not be mapped because the database provider does not support this type

想咨询是否可以通过Entity Framework Core实现该需求,还是应该采用存储过程执行上述T-SQL代码?


解决方案

完全可以通过EF Core实现你的需求,无需依赖存储过程,具体步骤如下:

1. 安装必要的NuGet包

在.NET Core 6中,EF Core对SQL Server地理类型的支持需要依赖以下两个包:

  • Microsoft.EntityFrameworkCore.SqlServer(EF Core SQL Server核心提供者)
  • Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite(为SQL Server添加NetTopologySuite的空间类型支持)

2. 配置DbContext

在你的DbContext的OnConfiguring方法中,启用NetTopologySuite支持,让EF Core能正确映射SQL Server的Geography列:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(
        "你的数据库连接字符串",
        x => x.UseNetTopologySuite());
}

3. 实体类定义

使用NetTopologySuite.Geometries.Point类型映射SQL Server的Geography列,注意指定SRID为4326(WGS84坐标系,对应SQL Server地理类型的默认坐标系):

using NetTopologySuite.Geometries;

public class GeographyAreas
{
    // 其他业务属性...
    public Point Geography { get; set; }
}

4. 编写LINQ查询

直接使用Distance方法即可,EF Core会自动将其转换为SQL Server的STDistance函数,实现球面距离计算(单位为米):

using NetTopologySuite.Geometries;

// 创建对应SRID的几何工厂
var geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);
// 注意构造Point时参数顺序为(经度, 纬度),对应WKT的POINT格式
var origin = geometryFactory.CreatePoint(new Coordinate(-93.123, 44.456));
var dist = 40000;

List<GeographyAreas> results = _context.GeographyAreas
    .Where(x => x.Geography.Distance(origin) <= dist)
    .ToList();

关键说明

  • 虽然NetTopologySuite的Point属于Geometry类型,但通过UseNetTopologySuite()配置后,它会正确映射到SQL Server的Geography列,并且支持地理空间的球面计算逻辑。
  • 确保数据库中Geography列的SRID为4326,若使用其他坐标系,需同步调整代码中GeometryFactory的SRID参数。

备选方案(若上述方法受限)

如果因特殊原因无法使用NetTopologySuite,也可以通过EF Core原生SQL查询实现,无需创建存储过程:

var originWkt = "POINT(-93.123 44.456)";
var dist = 40000;

var results = _context.GeographyAreas
    .FromSqlRaw(@"
        SELECT * FROM dbo.GeographyAreas 
        WHERE GEOGRAPHY::STGeomFromText({0}, 4326).STDistance(Geography) <= {1}",
        originWkt, dist)
    .ToList();

内容的提问来源于stack exchange,提问作者shage_in_excelsior

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 04:45:35