无法加载SqlServerSpatial.dll文件

33
我正在尝试在C# .Net项目中使用SqlServer空间CLR类型。我想使用SqlGeometry从我的数据库查询空间记录。
我已经在本地机器上使用Visual Studio 2010运行单元测试成功连接到远程SqlServer机器。一切正常。
然后,我将WCF Rest服务发布到我的本地IIS实例中,该服务访问与单元测试相同的类库以执行一些空间查询,但失败了。
我遇到了一个错误,提示:
“无法加载DLL SqlServerSpatial.dll:找不到指定的模块。”
我已经通过以下方式进行了搜索,并找到了很多答案 - 没有一个适用于我。
- 将CLR类型注册到GAC中 - 安装64位,以及稍后安装32位版本的VC++ - 尝试使用不同的Microsoft.SqlServer.Types dll版本的多种变化
目前我唯一没有做的事情是在实际的SqlServer盒子上安装任何东西。这对我来说似乎是不必要的。
在这一点上,我唯一能想到的原因是权限问题,因为它在IIS应用程序池中运行,而不是在工作单元测试的Studio内部。
请注意,在我的项目中,我从未引用过错误消息中提到的dll。该dll存在于sql框架中,但我无法将其添加到studio中,因为当我尝试时会给出一些消息。
我已经尝试了很多方法,但已经无法继续尝试。这就像90年代的dll地狱重现。

7
当然,在我发完这个帖子之后,我自己找到了答案。在IIS应用程序池中,我必须将“启用32位应用程序”更改为True。 - VBAHole
2
我遇到了同样的问题,并按照你所说的将“启用32位应用程序”设置为true来解决了。 - Ricky
1
或者安装 x86(32 位)版本的 CLR 类型 DLL。 - jao
1
来自未来的我发现,如果你在64位的IIS环境中运行应用程序池,需要将其设置为允许32位应用程序。我现在正在重写一个项目,但无法加载该程序集以使开发站点正常工作。这就是问题所在,一旦设置正确,应用程序就可以正常启动了。我尝试了所有解决方案,但都没有成功。 - Tommy
1
刚刚我也遇到了同样的问题,但没有明显的原因 - 它一直在工作,然后突然停止了。将应用程序池设置更改为允许32位应用程序即可解决问题。谢谢! - MK_Dev
从C:\ Program Files(x86)\ Microsoft SQL Server \ 100 \ SDK \ Assemblies导入Microsoft.SqlServer.Types.dll对我解决了这个问题。 - EvilInside
11个回答

36

我在一台安装了Windows Server 2012的机器上遇到了同样的问题。在\Windows\System32目录下找到了一个名为SqlServerSpatial110.dll的文件,但没有SqlServerSpatial.dll。解决方案是在该机器上安装Microsoft System CLR Types for SQL Server 2008 R2。

  1. http://www.microsoft.com/zh-cn/download/details.aspx?id=26728
  2. 点击下载
  3. 根据您的处理器架构之一进行勾选:

    • 1033\x64\SQLSysClrTypes.msi
    • 1033\x86\SQLSysClrTypes.msi
    • 1033\IA64\SQLSysClrTypes.msi
  4. 点击下一步


2
SQL 2012也安装了这个dll,但SQL 2014没有!它安装了SqlServerSpatial120.dll版本,这并不能解决问题。 - Alexandre
1
@Alexandre 如果我们只安装了Sql 2014,那么解决方案是什么?我们需要卸载它并安装2012,还是可以在2014安装的基础上安装2012类型? - Ebsan
1
安装 Microsoft System CLR Types for SQL Server 2008 R2,链接在答案中。 - Alexandre
1
这个链接已经失效了,我通过谷歌搜索也找不到这个下载链接。有人知道在哪里可以下载到吗? - Mark Heath
2
如果您在x64计算机上运行x86进程,则需要获取1033\x86\SQLSysClrTypes.msi而不是x64版本。 - DJA
显示剩余2条评论

29

我的问题和你的类似:我将我的 ASP.NET MVC 项目安装在远程 Azure 虚拟机上,然后出现了这个异常:

"Unable to load DLL 'SqlServerSpatial110.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)" 
为解决这个问题,我按照以下步骤进行操作:
  1. 我在我的项目中添加了缺失包的引用:

PM> Install-Package Microsoft.SqlServer.Types
  • 接着,我强制勾选了SqlServerSpatial110.dll的“输出目录中复制”选项为“始终复制”(可能这一步并非严格必要...

  • 对于ASP.NET项目,您需要将以下代码行添加到Global.asax.cs中的Application_Start方法中:

  • SqlServerTypes.Utilities.LoadNativeAssemblies(Server.MapPath("~/bin"));
    

    这个最后的步骤非常重要,因为如果没有这行代码,DLL将不会被 Web 应用程序加载。


    3
    按照您的指示做了,现在运作良好。(第二步是不必要的) - Kevin Farrugia
    4
    我安装了 Microsoft.SqlServer.Types 包,但是在我的项目中无法识别 SqlServerTypes 类型。 - Shimmy Weitzhandler
    2
    作为 NuGet 包内容的一部分,将添加一个 C# 文件到项目中,其中包含 SqlServerTypes.Utilities。NuGet 还将运行安装脚本,将 DLL 复制到有用的位置,但如果您使用 Paket 作为包管理器,则不会运行安装脚本(作为一项功能),因此还需要进行更多操作。 - TheQuickBrownFox

    8
    我多年来一直在WPF和ASP.NET应用程序中使用Microsoft.SqlServer.Types.dll来处理SqlGeometry类型和空间查询(自版本10以来),这里是我发现的最新提示,可以成功加载SqlServerSpatialXXX.dll作为Microsoft.SqlServer.Types.dll的先决条件之一。
    • VS项目(例如C#)中可以通过引用Microsoft.SqlServer.Types.dll来使用SqlGeometrySqlGeography类型。
    • Microsoft.SqlServer.Types.dll是一个托管库,有一些非托管库作为先决条件,它们像SqlServerSpatialXXX.dllmsvcrXXX.dll
    • 自SQL Server 2008以来,不同版本的Microsoft.SqlServer.Types.dll可用,但我没有看到从2012年开始的任何功能变化。

    考虑64位/32位问题

    • 对于64位机器,如果您安装了Sql Server的CLR类型,则可以在Windows/System32中找到这些先决条件文件的64位版本,也可以在Windows/SysWOW64文件夹中找到这些先决条件文件的32位版本。
    • 如果机器上没有安装CLR类型,则应根据您的项目(32位或64位)手动加载适当版本(32位/64位)的这些先决条件,否则您将会出现错误,例如:

    Error Loading SqlServerSpatialXXX.dll

    您可以使用Environment.Is64BitProcess在C#中在运行时检查32位/64位问题。以下是示例代码:

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr LoadLibrary(string libname);
    
    private static void LoadNativeAssembly(string nativeBinaryPath, string assemblyName)
    {
        var path = Path.Combine(nativeBinaryPath, assemblyName);
    
        if (!File.Exists(path))
        {
            throw new FileNotFoundException($"{path} not found");
        }
    
        var ptr = LoadLibrary(path);
        if (ptr == IntPtr.Zero)
        {
            throw new Exception(string.Format(
                "Error loading {0} (ErrorCode: {1})",
                assemblyName,
                Marshal.GetLastWin32Error()));
        }          
    }
    
    public static void LoadNativeAssembliesv13(string rootApplicationPath)
    {
        var nativeBinaryPath = Environment.Is64BitProcess
        ? Path.Combine(rootApplicationPath, @"SqlServerTypes\x64\")
        : Path.Combine(rootApplicationPath, @"SqlServerTypes\x86\");
    
        LoadNativeAssembly(nativeBinaryPath, "msvcr120.dll");
        LoadNativeAssembly(nativeBinaryPath, "SqlServerSpatial130.dll");
    }
    

    考虑不同项目类型中的二进制路径 建议在项目的执行路径中有一个名为SqlServerTypes的文件夹,像这样:

    SqlServerTypes>x64

    SqlServerTypes>x32

    并像这样加载非托管程序集。
    Utilities.LoadNativeAssembliesv13(Environment.CurrentDirectory); //WPF
    Utilities.LoadNativeAssembliesv13(HttpRuntime.BinDirectory); //ASP.NET 
    

    使用ADO.NET从Sql Server读取SqlGeometry时出现的问题 无论您使用哪个版本的Microsoft.SqlServer.Types.dll,如果您尝试使用ADO.NET从Sql Server 读取它们,您可能会遇到转换异常,因为SQL Client默认会加载Microsoft.SqlServer.Types.dll的10.0.0.0版本。在这种情况下,几年前我尝试了WKB(方法1和2)和WKT作为将不同版本的Microsoft.SqlServer.Types.dll之间的SqlGeometry类型进行转换的媒介,并发现WKB大约快10倍,但是几个月前我发现使用程序集重定向我们可以强制程序加载我们正在使用的版本,并使用简单的转换即可获得SqlGeometry(方法3)
    private List<SqlGeometry> SelectGeometries(string connectionString)
    {
        SqlConnection connection = new SqlConnection(connectionString);
        var command = new SqlCommand(select shapeCol from MyTable, connection);
        connection.Open();
        List<SqlGeometry> geometries = new List<SqlGeometry>();
        SqlDataReader reader = command.ExecuteReader();
        if (!reader.HasRows)
        {
            return new List<SqlGeometry>();
        }
        while (reader.Read())
        {
            //approach 1: using WKB. 4100-4200 ms for hundred thousands of records
            //geometries.Add(SqlGeometry.STGeomFromWKB(new System.Data.SqlTypes.SqlBytes((byte[])reader[0]), srid).MakeValid());
            //approach 2: using WKB. 3220 ms for hundred thousands of records
            //geometries.Add(SqlGeometry.Deserialize(reader.GetSqlBytes(0))); 
            //approach 3: exception occur if you forget proper assembly redirection. 2565 ms for hundred thousands of records
            geometries.Add((SqlGeometry)reader[0]);
        }
        connection.Close();
        return geometries;
    }
    

    1
    请在您的回答中包含LoadNativeAssembly的实现吗? - Shimmy Weitzhandler

    4
    我在一台Windows Server 2008 R2机器上遇到了问题(Azure VM),但以上步骤均未能解决问题。我安装了CLR类型,并将文件放入我的Web应用程序的BIN文件夹中,但仍然没有解决问题。最终我找到了Microsoft的这篇博客,它起作用了。我在此留下网址,以防其他人需要。

    http://blogs.msdn.com/b/adonet/archive/2013/12/09/microsoft-sqlserver-types-nuget-package-spatial-on-azure.aspx

    以下是说明:

    1. 打开Visual Studio并打开NuGet包管理器
    2. 搜索“Microsoft.SqlServer.Types”
    3. 安装...

    这个包将安装必要的.DLL文件到您的解决方案/项目中。它还会将一些其他库直接复制到您的/bin目录中。您必须在global.asax.cs/vb文件中引用这些附加库。 NuGet包中包含如何执行此操作的说明。以下是NuGet包的直接链接(希望微软不会将其移至无人问津的地方)。

    https://www.nuget.org/packages/Microsoft.SqlServer.Types/


    请不要简单地发布URL,这篇博客文章已经不存在了。如果您可以发布原始博客内容的摘要或副本,那将非常有帮助。当然仍然需要引用它,但如果它是一个外部网站(不是SO),那么您无法保证它会永久在线。 - Chris Schaller
    @ChrisSchaller 完成。干杯! - Jason

    4
    尽管安装了 SQL Server 14.x,但 VS 仍坚称找不到 SqlServerSpatial110.dll。
    安装 Microsoft System CLR Types for SQL Server 2008 R2 也没有解决问题。我尝试安装版本号为 10.5 的 Microsoft.SqlServer.Types,但出现了方法签名不匹配的 PInvoke 错误。
    因此,我安装了 Microsoft.SqlServer.Types 14.x,然后将 SqlServerSpatial140.dll 文件重命名为 SqlServerSpatial110.dll,并在 /x86 和 /x64 文件夹中以及 Loader.cs 文件中做了相同的修改。出于某种原因,这似乎奏效了。

    1
    除了通过NuGet安装Microsoft.SqlServer.Types库之外,我发现您还需要添加一个绑定重定向来代替重命名DLL。 <dependentAssembly> <assemblyIdentity name="Microsoft.SqlServer.Types" publicKeyToken="89845dcd8080cc91" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-14.0.0.0" newVersion="14.0.0.0" /> </dependentAssembly> - Derek Flenniken
    这是一个更好的做法。谢谢分享。 - Adam

    3

    我有一个旧的(2009年)asp.net webform vb.net项目,在另一台服务器上出现了这个错误。我不得不在web.config中添加以下运行时:

    最初的回答:

    <configuration>
      <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="Microsoft.SqlServer.Types" publicKeyToken="89845dcd8080cc91" />
            <bindingRedirect oldVersion="1.0.0.0-11.0.0.0" newVersion="10.0.0.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>
    

    http://biandintegration.blogspot.com/2017/12/solved-unable-to-load-dll.html


    2

    我在使用Windows Server 2012 R2的Godaddy VPS时遇到了相同的问题。

    I Resolved it by Updating my EF5 to EF6
    
    在包管理器控制台中运行以下命令以将EF5更新到最新的EF版本。
    Install-Package EntityFramework 
    

    1

    我在一个ASP.NET MVC 5项目中遇到了类似的问题。一段时间以前,我不得不添加一行代码来指定程序集名称,如下所示:

    SqlServerTypes.Utilities.LoadNativeAssemblies(Server.MapPath("~/bin"));
    SqlProviderServices.SqlServerTypesAssemblyName = Assembly.GetAssembly(typeof(Microsoft.SqlServer.Types.SqlGeography)).FullName;
    

    我最近部署到一个新的测试服务器,又遇到了这个错误。它试图加载版本12,但我现在指定了我想要的确切版本,它就按预期工作了。

    SqlServerTypes.Utilities.LoadNativeAssemblies(Server.MapPath("~/bin"));
    SqlProviderServices.SqlServerTypesAssemblyName = "Microsoft.SqlServer.Types, Version=14.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91";
    

    希望这能对某些人有所帮助。

    哇,好奇怪啊。我们的一个解决方案在所有开发机器上都能正常工作,除了我的笔记本电脑,我们有第一行但没有 SqlProviderServices.SqlServerTypesAssemblyName 行,在添加后修复了这个问题。 - agrath

    1

    将 Microsoft.SqlServer.Types.dll 从引用中移除,并使用 Nuget 进行安装。在安装前检查您的版本。x86 和 x64 的程序集将会被安装到项目中。


    请检查以下内容: https://www.codeproject.com/Questions/833069/Could-not-load-file-or-assembly-Microsoft-SqlServe - Robson Douglas
    Nuget包对我很有效。只需要确保在csproj中删除对DLL的引用。另外,对于较旧版本的LLBL,我必须使用nuget包的第10个版本。 - Nick Gallimore

    0

    只需使用NuGet安装Microsoft.SqlServer.Types


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接