I am currently struggling with deployment problems caused by Microsoft.SqlServer.Types
and its associated unmanaged library, SqlServerSpatial110.dll
- both for Microsoft SQL Server 2012. The problems are trivially easy to solve, just typical missing DLL issues, but I am trying to decide on the perfect way to handle these dependencies.
Firstly, I must declare that I do not agree with the popular opinion that manually deploying either library (usually by copying them into your project's output directory or, horrifically, into System32
itself) is correct. Microsoft provide redistributable MSI installers for these files and those installers put the files into system locations. It seems obvious that they want us to depend on those redistributables being installed separately or as part of the tried and tested dependency mechanisms built into MSI itself.
At the time of posting, the latest version of these redistributables could be downloaded from: http://www.microsoft.com/en-gb/download/details.aspx?id=43339
For SqlServerSpatial110.dll
, there does not appear to be any problem. The MSI installers (platform specific) drop the file into either Windows\System32
or Windows\SysWOW64
as is appropriate and all is well.
The managed wrapper library, Microsoft.SqlServer.Types.dll
, is more confusing.
It seems to me that the file is dropped into the Global Assembly Cache - after running the MSIs, on my machine, I can see it located at C:\Windows\assembly\GAC_MSIL\Microsoft.SqlServer.Types\11.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.Types.dll
and that file has the correct version and modified-date.
Oddly, I can't see it in Visual Studio's reference browser or in Windows Explorer directly - only in my very old fashioned file-system search tool by Mythicsoft. Why can't I see it?
Since the file is almost in the GAC, I would guess that projects referencing it should not make a local copy of it - they should rely on it being there on the target system. I tested this assumption and it worked:
- Manually copy
Microsoft.SqlServer.Types.dll
from its location inC:\Windows\assembly\GAC_MSIL
- Add a reference to the copy.
- Ensure that the reference has
Copy Local
set toFalse
- Build the project and ensure that
Microsoft.SqlServer.Types.dll
is definitely not present in the output. - Test project... no problems!
So, if the assembly can be resolved from the GAC at runtime to satisfy this dependency, why isn't it shown in the reference browser when adding a reference? Why do I have to copy it out of the GAC and reference the copy?
In my mind, the ideal work-flow would be this:
- Install redistributable MSIs on development machines.
- Ensure redistributable is installed on target machines by listing it as an MSI dependency if your product is deployed via MSI or manually installing it if you're using 'xcopy' deployment.
- Reference
Microsoft.SqlServer.Types
from the GAC using the reference browser just like any framework library. (Copy Local
will be set toFalse
by default.) - At runtime,
Microsoft.SqlServer.Types
(platform agnostic) will be resolved from the GAC and the appropriate copy of the unmanaged library will be loaded from the system location depending on the process architecture. - No worries!
Clearly, step 3 doesn't happen. Am I missing something? Perhaps I am misunderstanding the GAC itself - it wouldn't be the first time. Why has Microsoft done it this way? Can I get closer to my ideal work-flow?
Perhaps there is an entirely different way of managing this dependency - something I have clearly not thought of. If so, what is it? How do you handle it?