How to use ILMerge with SQL Server 2005 CLR assemblies plus an XmlSerializer

640 Views Asked by At

I have four assemblies (plus the .NET 3.5 system.core) that I am installing as unsafe CLR assemblies in a SQL Server 2005 database. Installing the assemblies in the correct order (based on their dependencies) works fine, and I am able to use the CLR functions I need. If possible, I would like to use ILMerge on the four assemblies so that I can install just one DLL. Only one assembly is directly referenced from the SQL side anyway; the others are dependencies. It happens that one of those four assemblies is an XmlSerializer assembly generated with sgen, which is required because the SQL Server CLR will not allow the serializer to be created at runtime.

In the following discussion, the assemblies are called:

  1. ClrIntegration.dll (this is a CLR library in Visual Studio 2008 and is the only library actually referenced from SQL)
  2. CalcLibrary.dll (this is just a .NET 3.5 library that ClrIntegration.dll uses)
  3. CalcLibrary.Schema.dll (this is a .NET 3.5 library whose code is generated entirely by running xsd.exe on two .xsd files -- CalcLibrary.dll uses this library)
  4. CalcLibrary.Schema.XmlSerializers.dll (this is generated by running sgen on CalcLibrary.Schema and is used automatically by an XmlSerializer in CalcLibrary.dll)

To my knowledge, it is not possible to reference the version of CalcLibrary.dll that is in my VS2008 solution directly from the ClrIntegration project. Instead, I have to install CalcLibrary.dll on a running SQL Server 2005 instance and add it as a database reference to the ClrIntegration project. This is a nuisance, but I've made it work so far.

The basic command line I am using as a post-build event in the ClrIntegration project is:

"c:\Program Files (x86)\Microsoft\ILMerge\ILMerge.exe" /targetplatform:v2 /out:ClrMergedAssembly.dll \
"$(TargetDir)ClrIntegration.dll" \
"$(SolutionDir)Source\CalcLibrary\$(OutDir)CalcLibrary.dll" \
"$(SolutionDir)Source\CalcLibrary.Schema\$(OutDir)CalcLibrary.Schema.dll" \
"$(SolutionDir)Source\CalcLibrary.Schema\$(OutDir)CalcLibrary.Schema.XmlSerializers.dll"

I'm running into a few problems here.

  1. If I just run ILMerge as shown above, it works, and I get ClrMergedAssembly.dll. I can install ClrMergedAssembly.dll on SQL Server 2005, but when I try to use it, anything that uses XmlSerializer gives me an error like:

    A .NET Framework error occurred during execution of user-defined routine or aggregate "Whatever":
    System.InvalidOperationException: Cannot load dynamically generated serialization assembly. In some hosting environments assembly load functionality is restricted, consider using pre-generated serializer.

    This is the same error I get when not generating the XmlSerializer at all. I found this excellent blog entry stating that sgen needs to be run again after ILMerge, but doing so creates two problems. First, I really need sgen to be run only on CalcLibrary.Schema.dll. Running it on the whole assembly will fail badly; in fact, that is why CalcLibrary.Schema is separate from CalcLibrary in the first place. Second, having the serializer be separate somewhat defeats the purpose of using ILMerge at all: I want just one DLL to deploy. Are there any solutions here?

  2. The ILMerge.doc file that comes with the ILMerge installation seems to suggest that adding /union and/or /closed might solve some problems. But, using either /union alone or /union along with /closed causes ILMerge to fail with the following error:

    An exception occurred during merging:
    Unresolved assembly reference not allowed: CalcLibrary.

    A stack trace follows the error. My suspicion is that, because ClrIntegration must reference the database version of CalcLibrary rather than the VS2008 solution's version, ILMerge cannot find the type and, therefore, cannot complete the union even though CalcLibrary.dll is the same library. Is my suspicion correct? Is there any way around this issue?

1

There are 1 best solutions below

0
On BEST ANSWER

You can't. The framework code always looks for the sgen generated classes in a different assembly - the one named with .XmlSerializers suffix - and it is hardcoded in the framework. Check with your decompilation tool of choice.