Linux环境下SqlServerSpatial160.dll缺失及解决方案咨询
我正在Linux环境下构建并运行.NET Core 7.0解决方案,该方案大量使用SQL Server空间类型(对应NuGet包:Microsoft.SqlServer.Types),而该类型依赖本地SQL Server类型实现库SqlServerSpatial160.dll。
比如NuGet包中GLNativeMethods.cs的代码片段:
[DllImport("SqlServerSpatial160.dll")] public static extern double GeodeticPointDistance([In] Point p1, [In] Point p2, [In] EllipsoidParameters ep); [DllImport("SqlServerSpatial160.dll")] private static extern GL_HResult Outline( [In] GeoMarshalData g, [In, Out] GeoDataPinningAllocator resultAllocator);
NuGet包仅提供Win64和Win86的库文件,没有Linux版本,调用空间类型相关代码时出现如下错误:
Failed Swyfft.Common.UnitTests.Helpers.BestPointUnitTests.GetBestLatLon_H2H1_ShouldReturnHigh [1 ms] Error Message: System.DllNotFoundException : Unable to load shared library 'SqlServerSpatial160.dll' or one of its dependencies. In order to help diagnose loading problems, consider using a tool like strace. If you're using glibc, consider setting the LD_DEBUG environment variable: /home/ken/swyfft_web/Swyfft.Common.UnitTests/bin/Debug/net7.0/runtimes/linux-x64/native/SqlServerSpatial160.dll.so: cannot open shared object file: No such file or directory /usr/share/dotnet/shared/Microsoft.NETCore.App/7.0.2/SqlServerSpatial160.dll.so: cannot open shared object file: No such file or directory /home/ken/swyfft_web/Swyfft.Common.UnitTests/bin/Debug/net7.0/SqlServerSpatial160.dll.so: cannot open shared object file: No such file or directory /home/ken/swyfft_web/Swyfft.Common.UnitTests/bin/Debug/net7.0/runtimes/linux-x64/native/libSqlServerSpatial160.dll.so: cannot open shared object file: No such file or directory /usr/share/dotnet/shared/Microsoft.NETCore.App/7.0.2/libSqlServerSpatial160.dll.so: cannot open shared object file: No such file or directory /home/ken/swyfft_web/Swyfft.Common.UnitTests/bin/Debug/net7.0/libSqlServerSpatial160.dll.so: cannot open shared object file: No such file or directory /home/ken/swyfft_web/Swyfft.Common.UnitTests/bin/Debug/net7.0/runtimes/linux-x64/native/SqlServerSpatial160.dll: cannot open shared object file: No such file or directory /usr/share/dotnet/shared/Microsoft.NETCore.App/7.0.2/SqlServerSpatial160.dll: cannot open shared object file: No such file or directory /home/ken/swyfft_web/Swyfft.Common.UnitTests/bin/Debug/net7.0/SqlServerSpatial160.dll: cannot open shared object file: No such file or directory /home/ken/swyfft_web/Swyfft.Common.UnitTests/bin/Debug/net7.0/runtimes/linux-x64/native/libSqlServerSpatial160.dll: cannot open shared object file: No such file or directory /usr/share/dotnet/shared/Microsoft.NETCore.App/7.0.2/libSqlServerSpatial160.dll: cannot open shared object file: No such file or directory /home/ken/swyfft_web/Swyfft.Common.UnitTests/bin/Debug/net7.0/libSqlServerSpatial160.dll: cannot open shared object file: No such file or directory Stack Trace: at Microsoft.SqlServer.Types.GLNativeMethods.GeodeticPointDistance(Point p1, Point p2, EllipsoidParameters ep) at Microsoft.SqlServer.Types.SqlGeography.STDistance(SqlGeography other) at Swyfft.Common.Geo.SqlGeographyHelpers.GetDistance(IMappable p1, IMappable p2) in /home/ken/swyfft_web/Swyfft.Common/Geo/SqlGeographyHelpers.cs:line 104
问题解答
1. 是否存在SqlServerSpatial160.dll的Linux版本?
不存在官方提供的SqlServerSpatial160.dll Linux版本。Microsoft.SqlServer.Types NuGet包仅包含Windows平台的本地库,Linux环境下无法直接加载该DLL文件。
2. Linux上使用SQL Server空间类型的解决方案
针对Linux环境,有以下几种可行方案:
方案一:将空间计算逻辑迁移到SQL Server端执行
将原本在应用层进行的空间计算(比如STDistance这类操作)迁移到SQL Server数据库中执行,应用层仅负责传递参数和接收计算结果。SQL Server for Linux完全支持空间类型和相关函数,可避开本地依赖库的问题。方案二:使用跨平台的空间处理库替代
替换Microsoft.SqlServer.Types,改用跨平台的开源空间处理库:NetTopologySuite:支持大部分SQL Server空间类型的等价操作,完全跨平台,无需依赖本地DLL。GeoAPI:与NetTopologySuite配合使用,提供统一的空间数据接口,便于替换现有代码中的SQL Server空间类型逻辑。
方案三:升级到.NET 8+并使用内置支持
从.NET 8开始,Microsoft.Data.SqlClient库内置了对SQL Server空间类型的跨平台支持,无需依赖外部的Microsoft.SqlServer.TypesNuGet包和本地DLL。如果项目可以升级到.NET 8或更高版本,这是最简洁的解决方案。方案四:通过Wine运行Windows库(不推荐)
可尝试用Wine在Linux上加载SqlServerSpatial160.dll,但该方式存在兼容性问题、性能损耗,且维护成本高,仅适用于临时测试场景,不建议在生产环境使用。
内容的提问来源于stack exchange,提问作者Ken Smith

