33

I am trying to use the SqlServer Spatial CLR types in a C# .Net project. I want to use SqlGeometry to query spatial records out of my db.

I have this working on my local machine in a unit test running in Visual Studio 2010 hitting a remote SqlServer machine. All good.

I then publish a WCF Rest service to my local IIS instance that has a service that hits the same class library as the unit test to do some spatial querying and it fails.

I get an error saying

Unable to load DLL SqlServerSpatial.dll : The specified module could not be found.

I have googled this and found many, many answers - none work for me. I have:

  • registered the CLR types with the GAC
  • install the 64-bit, and later also, the 32-bit version of the VC++
  • tried many variations of using different Microsoft.SqlServer.Types dll versions

The only thing I have not done, and frankly refuse to do, is to install anything on the actual SqlServer box. This seems unnecessary to me.

At this point the only thing that I can think is causing this is a permissions issue because it is running in an IIS app pool and not inside Studio where it works in the unit test.

Note that in my project I NEVER make reference to the dll mentioned in the error message. That dll is present on the sql box but I can't add it to studio as it gives some message when i try to. I'm running out of things to try here. It's 90's dll hell all over again.

Hossein Narimani Rad
  • 31,361
  • 18
  • 86
  • 116
VBAHole
  • 1,508
  • 2
  • 24
  • 38
  • 7
    of course right after i post this i find the answer myself. In the IIS app pool i had to change 'Enable 32-bit applications' to True. – VBAHole Jan 10 '13 at 19:45
  • 2
    I got the same problem and resolved by setting "Enable 32-bit applications" t true as you said. – Ricky Dec 13 '13 at 14:56
  • 1
    or install the x86 (32 bit) version of the CLR types DLL. – jao Aug 23 '15 at 08:01
  • 1
    Way from the future, but I found that the app pool needed to be set to allow 32bit applications if you were running in a 64bit IIS environment. Working on a rewrite on one now and couldn't get the dev site to load that assembly. That was the difference and fired right up. Tried all solutions here to no avail. – Tommy Mar 17 '16 at 03:57
  • 1
    Just had the same thing happen to me but for no obvious reason - it was working, then just stopped. Changing the app pool setting to allow for 32-bit applications worked. Thank you! – MK_Dev Dec 22 '16 at 16:59
  • Importing Microsoft.SqlServer.Types.dll from C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies worked for me to resolve the problem. – EvilInside Apr 14 '17 at 21:06

11 Answers11

36

I had the same problem on a Windows Server 2012 machine. It had an SqlServerSpatial110.dll file in \Windows\System32, but no SqlServerSpatial.dll. The solution was installing the Microsoft System CLR Types for SQL Server 2008 R2 on the machine.

  1. http://www.microsoft.com/en-us/download/details.aspx?id=26728
  2. Click Download
  3. Check off one of these depending on your processor architecture:

    • 1033\x64\SQLSysClrTypes.msi
    • 1033\x86\SQLSysClrTypes.msi
    • 1033\IA64\SQLSysClrTypes.msi
  4. Click Next

Marcelo Mason
  • 6,750
  • 2
  • 34
  • 43
  • 2
    SQL 2012 installs this dll too, SQL 2014 don't! It installs the SqlServerSpatial120.dll version, which doesn't solve the problem. – Alexandre Jul 27 '15 at 16:53
  • 1
    @Alexandre So what's the solution if we only have Sql 2014 installed? Would we have to uninstall it and install 2012 or could we install the 2012 types on top of the 2014 install? – Ebsan Jul 30 '15 at 18:30
  • 1
    Install the Microsoft System CLR Types for SQL Server 2008 R2, the link is in the answer – Alexandre Jul 30 '15 at 18:31
  • 1
    the link is broken and I can't seem to find this download by googling. Anyone know where it can be downloaded from? – Mark Heath Jan 06 '16 at 13:09
  • 2
    If you are running an x86 process on an x64 box, then you need to get 1033\x86\SQLSysClrTypes.msi not the x64 version. – DJA Jul 17 '16 at 23:50
  • The whole idea frightens me. What's gonna be when I'm gonna have to deploy it? Am I also gonna have to eat this pain? – Shimmy Weitzhandler Apr 28 '17 at 13:12
  • Just to add, installing the CLRs for 2008 did nothing to fix my issue. I had to install the CLR types 2012: https://www.microsoft.com/en-gb/download/details.aspx?id=29065 – Dalbir Singh Oct 05 '17 at 12:51
29

My problem was similar to yours: I installed my ASP.NET MVC project on a remote Azure Virtual Machine and I got this exception:

"Unable to load DLL 'SqlServerSpatial110.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)" 

To solve the issue I followed these steps:

  1. I added the reference to the missing package in my project:

    PM> Install-Package Microsoft.SqlServer.Types
    
  2. Then I forced the "Copy to output directory" option to "Copy always" for the SqlServerSpatial110.dll (probably this step is not strictly required...)

  3. For ASP.NET projects, you need to add the following line of code to the Application_Start method in Global.asax.cs:

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

    This last step was fundamental for me, because whitout this line of code the DLL is not loaded by the web application.

davioooh
  • 23,742
  • 39
  • 159
  • 250
  • 3
    Followed your instructions and it's working well. (step 2 was not necessary) – Kevin Farrugia Sep 30 '16 at 09:30
  • 4
    I installed the `Microsoft.SqlServer.Types` package, but the type `SqlServerTypes` is unrecognized in my project. – Shimmy Weitzhandler Sep 20 '17 at 01:15
  • 2
    A C# file is added to the project as part of the NuGet package content and it contains `SqlServerTypes.Utilities`. NuGet will also run an install script that copies the DLLs to useful locations but if you use Paket as a package manager, it doesn't run install scripts (as a feature) so there will be more to be done. – TheQuickBrownFox Dec 14 '17 at 13:06
8

I have been using Microsoft.SqlServer.Types.dll in WPF and ASP.NET apps to work with SqlGeometry type and spatial queries for years (since v.10) and here is the latest tips I found to successfully load the SqlServerSpatialXXX.dll as one of the prerequisites of the Microsoft.SqlServer.Types.dll.

  • SqlGeometry and SqlGeography types can be used in VS projects (e.g. C#) by referencing the Microsoft.SqlServer.Types.dll.
  • Microsoft.SqlServer.Types.dll is a managed library and has some unmanaged library as prerequisites and they are like SqlServerSpatialXXX.dll and msvcrXXX.dll
  • Since Sql Server 2008, different versions of Microsoft.SqlServer.Types.dll are available, however, I don't see any functionality change from 2012 on.

Consider 64bit/32bit issues

  • For 64 bit machanies, if you install CLR Types for Sql Server, you can find 64bit versions of these prerequisites files in Windows/System32 and also you can find 32bit versions of prerequisites files in Windows/SysWOW64 folder
  • If CLR Types are not installed on a machine, You should manually load proper versions (32bit/64bit) of these prerequisites based on your project (32bit or 64bit) otherwise you will errors like

Error Loading SqlServerSpatialXXX.dll

You can check 32bit/64bit issue at runtime in C# using Environment.Is64BitProcess. Here is a sample code:

[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");
}

Consider binary path in different project types It is recommended to have a folder named SqlServerTypes in the execution path of your project like this

SqlServerTypes>x64

SqlServerTypes>x32

and load unmanaged assemblies like this

Utilities.LoadNativeAssembliesv13(Environment.CurrentDirectory); //WPF
Utilities.LoadNativeAssembliesv13(HttpRuntime.BinDirectory); //ASP.NET 

Issues when using ADO.NET to read SqlGeometry from Sql Server Despite which version of Microsoft.SqlServer.Types.dll you are using, if you try to read them from Sql Server using ADO.NET you may encounter a cast exception because SQL Client will by default load version 10.0.0.0 of Microsoft.SqlServer.Types.dll. In this case some years ago I tried WKB (approach 1 and 2) and WKT as a medium to convert between SqlGeometry type for different version of Microsoft.SqlServer.Types.dll and found WKB is about 10 times faster but some month ago I found using assembly redirection we can force the program to load the version we are using and using a simple cast we can get the SqlGeometry (approach 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;
}
Hossein Narimani Rad
  • 31,361
  • 18
  • 86
  • 116
4

I was having issues on a Windows Server 2008 R2 machine (Azure VM), but none of the steps above were able to fix the issue. I installed the CLR types. I put the files in my web application's BIN folder. Still nothing. I finally came across this blog by the folks at Microsoft and it worked. I'm leaving the url here in case it can help anyone else.

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

I've put instructions below:

  1. Open Visual Studio and open the NuGet Package Manager
  2. Search for "Microsoft.SqlServer.Types"
  3. Install...

This package will install the necessary .DLLs into your solution/project. It will also copy some additional libraries directly into your /bin directory. You must wire up references to these additional libraries in your global.asax.cs/vb file. There are instructions on how to do this included in the NuGet package. Below is a direct link to the NuGet Package (hopefully MSFT doesn't move this into oblivion too).

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

Albireo
  • 10,977
  • 13
  • 62
  • 96
Jason
  • 2,390
  • 2
  • 18
  • 22
  • Please do not simply post URLs, this particular blog post no longer exists. It would have been mighty helpful if you posted a summary or a copy of the content from the original blog. Still reference it for sure, but if it is an external site (not SO) then you cannot guarantee it will remain online indefinitely. – Chris Schaller Dec 22 '16 at 03:25
  • @ChrisSchaller Done. Cheers! – Jason Jan 05 '17 at 20:08
4

Despite having SQL Server 14.x installed, VS kept insisting SqlServerSpatial110.dll was not found.

Installing Microsoft System CLR Types for SQL Server 2008 R2 did not fix it. I also tried to install the 10.5 version of Microsoft.SqlServer.Types, but received a PInvoke error about the method signature not matching.

So instead, I installed Microsoft.SqlServer.Types 14.x, then renamed the SqlServerSpatial140.dll file to SqlServerSpatial110.dll in both /x86 and /x64 folders and did the same in Loader.cs. For whatever reason, that seemed to do the trick.

Adam
  • 1,984
  • 2
  • 16
  • 19
  • 1
    In addition to installing via NuGet the `Microsoft.SqlServer.Types` library, I found you also need add a bindingredirect for the library instead of renaming the DLL. ` ` – Derek Flenniken Apr 03 '19 at 17:56
  • That's a much better way to do it. Thanks for sharing – Adam Apr 05 '19 at 03:34
2

I had the same issue in godaddy VPS with windows server 2012 r2

I Resolved it by Updating my EF5 to EF6

in package manager console run to EF5 to EF lalest

Install-Package EntityFramework 
Nur Uddin
  • 1,798
  • 1
  • 28
  • 38
2

I had an old (2009) asp.net webform vb.net project that gave me this error on another server. I had to add this runtime to the 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

François Breton
  • 1,158
  • 14
  • 24
1

Remove the Microsoft.SqlServer.Types.dll from References and use Nuget to instal. Check your version before install. The assemblies to x86 and x64 will be installed in the project.

  • Check it https://www.codeproject.com/Questions/833069/Could-not-load-file-or-assembly-Microsoft-SqlServe – Robson Douglas Jul 25 '18 at 13:16
  • The nuget package worked for me. Just had to make sure to remove references to the DLL in the csproj. Also with an older version of LLBL I had to use version 10 of the nuget package. – Nick Gallimore Jul 25 '18 at 15:42
1

I've been having a similar issue on an ASP.NET MVC 5 project. A while back I had to add a line to specify the Assembly name like so:

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

I recently deployed to a new test server and got this error again. It was trying to load version 12 for some reason. I now specify the exact version I want and it works as expected.

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

Hope this helps someone.

Andrew Grothe
  • 2,562
  • 1
  • 32
  • 48
  • Wow, weird af. A solution of ours is working fine on all development machines except my laptop and we had the first line but not the SqlProviderServices.SqlServerTypesAssemblyName line, fixed after adding that. – agrath Apr 15 '22 at 09:47
0

Here is what was causing this issue for me:-

There is a folder named SQLServerTypes in my project and when I looked inside the folder I found out that the .dll was actually missing. So downloading the .dll and pasting it inside the SQLServerTypes folder fixed the issue for me.

The issue was happening for me when I was trying to build my application.

Fakhar Ahmad Rasul
  • 1,595
  • 1
  • 19
  • 37
0

just install Microsoft.SqlServer.Types with nuget