如何在ASP.NET Core 7中用C#和NetTopologySuite正确检索SQL Server空间数据
解决SQL Server空间数据(Geometry)与EF Core/NetTopologySuite的适配问题
问题根源
你手动添加的HasConversion配置与EF Core SqlServer NetTopologySuite扩展的自动映射冲突了。当在UseSqlServer中调用UseNetTopologySuite()时,EF已经自动为NetTopologySuite的Geometry/Point类型配置了正确的SQL Server geometry类型映射,手动添加转换逻辑会打破内置类型处理流程,导致类型不匹配错误(如byte[]转string、泛型约束违反)。
修复步骤
1. 移除DbContext中的手动类型转换配置
删除OnModelCreating里Coordinates属性的HasConversion代码,保留基础配置:
modelBuilder.Entity<CoordinatesTable>(l => { l.Property(e => e.Coordinates) .HasColumnType("geometry") .HasColumnName("Coordinates"); // 移除所有HasConversion相关代码 });
2. 确认实体类与表结构匹配
你的实体类CoordinatesTable中Coordinates属性为NetTopologySuite的Point类型,SQL Server表的Coordinates列为geometry类型,该配置正确,无需修改。
3. 验证数据检索代码
直接使用EF Core常规查询方法即可,无需额外转换:
服务层查询示例
public List<CoordinatesTable> GetAllCoordinates() { return _dbContext.CoordinatesTable.ToList(); } public async Task<CoordinatesDto> GetCoordinatesAsync(int locationId) { return await _coordinatesRepository .GetAll() .Where(fe => fe.LocationId == locationId) .Select(fe => new CoordinatesDto { LocationId = fe.LocationId, Coordinates = fe.Coordinates }) .FirstOrDefaultAsync(); }
4. 转换为GeoJSON发送给Angular客户端
使用NetTopologySuite.IO.GeoJSON包将Point对象序列化为GeoJSON:
// 在服务层或DTO映射时处理 var geoJsonWriter = new GeoJsonWriter(); string geoJson = geoJsonWriter.Write(coordinatesDto.Coordinates); // 将geoJson字符串传给Angular客户端,或直接在DTO中返回该字符串
若需自动序列化,可在Startup/Program.cs中配置JSON序列化器支持NetTopologySuite类型:
services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new NetTopologySuite.IO.Converters.GeoJsonConverterFactory()); });
配置后直接返回Point类型属性时,会自动序列化为GeoJSON格式。
关键注意事项
- 确保包版本兼容:.NET7对应
Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite 7.0.10是正确的,NetTopologySuite 2.5.0和GeoJSON 4.0.0也与该版本兼容。 - 不要混合使用
Microsoft.SqlServer.Types的SqlGeometry和NetTopologySuite的Point,EF Core的NetTopologySuite扩展已封装两者转换,全程使用NetTopologySuite类型即可。
内容的提问来源于stack exchange,提问作者juststartingout
相关产品推荐
相关产品推荐

