Call WCF Service through SQL CLR - wcf

I have followed all the steps in below link.
http://support.microsoft.com/kb/913668 - Method 2
But still I'm facing the same error
'Cannot load dynamically generated serialization assembly. In some
hosting environments assembly load functionality is restricted,
consider using pre-generated serializer. after creating xmlserializer
assembly'.
Pleae help me on this

Referenced here: http://support.microsoft.com/kb/913668
MS SQL sandboxes .NET and doesn't allow you to do dynamic CLR generation. You can get around this by generating the assembly at compile-time using this as a post-build step:
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sgen.exe" /force "$(TargetPath)"
The referenced article has a couple other options, but if your schema is pre-determined, sgen is the way to go.

Related

Unable to execute stored procedure created in SQLCLR

I have create a stored procedure in SQLCLR (SQL Server Database Project, VS2012). I publish the stored procedure successfully to the database. But when I run the stored procedure in the database, I get an error.
Cannot load dynamically generated serialization assembly. In some hosting environments assembly load functionality is restricted, consider using pre-generated serializer. Please see inner exception for more information.
Note: after publishing, no xmlserializer.dll is created. Even generate serialization assembly is set to ON.
Are you using WCF within your SQLCLR assembly (or some other web services client)?
If so, you need to use the XML Serializer Generator tool to create the serialization assembly manually and then add it to SQL Server along with your original assembly.
There are more detailed instructions at the above link, but the command you'll need (which can be added as a post-build step for your project) is something along the lines of:
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\sgen.exe" /force "$(TargetPath)"
Then in SQL Server:
CREATE ASSEMBLY [(ProjectName).XmlSerializers.dll] from '(ProjectName).XmlSerializers.dll'
More details about sgen are available here.

SSDT add assembly to deploy

I have old project that uses WCF from withing C# CLR triggers for SQL Server. I was always installing it by running a script.
But I've decided to move on to SSDT project on VS 2012. I've imported project from empty database.
WCF functionality depends on several assemblies from .net framework
SMdiagnostics
System.Web
System.Messaging
system.identitymodel
system.identitymodel.selectors
microsoft.transactions.bridge
System.ServiceModel
So I have a reference to these dlls in my project. I also had them added to my project under Assemblies sub folder.
However when I create a deployment script, these assemblies are not in it.
So when I try to publish script to database I receive an error.
Assembly 'system.servicemodel, version=3.0.0.0, culture=neutral, publickeytoken=b77a5c561934e089.' was not found in the SQL catalog.
If I try to create custom script to add assemblies to db :
create assembly [SMdiagnostics]
from 'C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\SMdiagnostics.dll'
with permission_set = unsafe
go
I receive error
Error: SQL70502: The assembly source is not valid. Only binary literals are allowed.
How can I add assembly from .NET to be deployed along with my SSDT project?
Thanks.
To add a .NET assembly to a SSDT project:
In Solution Explorer, expand the project and right-click References.
In the Add References window, either browse for the assembly or choose from the Assemblies category.
Right-click on the added assembly and click Properties.
Make sure these properties are set:
Generate Sql Script: True
Model Aware: True
Permission Set: Safe/External/Unsafe (depending on the assembly)
Press F5 to deploy to LocalDB/Debug destination or choose Publish and Generate Script to verify the changes.
DACPACs (the result of a SSDT build) doesn't allow CREATE ASSEMBLY with paths because the DLL isn't included and the path can't be guaranteed on another host. Therefore only embedded binary literals are allowed in the DACPAC.

How do I use COM reference within SSIS package?

I'm trying to use the Microsoft Shell Controls And Automation COM object library (C:\Windows\System32\shell32.dll) from within an SSIS Script Task to manipulate .zip archives.
Unfortunately, although I have successfully added the relevant Reference and the Script Task compiles OK. I'm using VB.NET, for what it's worth. I get the following runtime error as soon as I try to create any objects defined within the library:
Error: 0x1 at Archive File: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException: Could not load file or assembly 'Interop.Shell32, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
File name: 'Interop.Shell32, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
at ST_a2650b7f39504eaa8c80e37a6736d957.vbproj.ScriptMain.Main()
I thought the Interop DLL would all be taken care of for me - does anyone know what step am I missing?
SSIS needs all .dll references to be registered with the GAC, you are correct.
You have different options regarding installing this dll into the GAC:
Drag and drop the .dll into the %windir%\assembly\ folder.
Use the gacutil.exe you are thinking about using: Regarding installing into the GAC using the gacutil, there is alot of useful information here: Global_Assembly_Cache. Basically, if you have the .NET framework installed (you are using VB.NET so no problem there), you will have a gacutil.exe in your Microsoft.NET folder.
(What I normally use when all else fails) Create a windows MSI project in Visual Studio that automatically does all this for you, useful info here: How to install assembly in the GAC using MSI
If you install that .dll in the GAC and you are still having problems, another option is to actually create a separate visual studio project that contains your logic for manipulating the needed zip files build it and call its exe from SSIS using the Execute Process Task. You can pass arguments specified in the SSIS package. Not very elegant, but it gets the job done if you are keen on using SSIS.
UPDATE:
The solution in this question did the trick SSIS Script Task COMException / FileNotFoundException error. The problem was in adding a signed reference of the dll, this answer provides a good step-by-step workaround for adding a COM reference within the SSIS Script Task.

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

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:
ClrIntegration.dll (this is a CLR library in Visual Studio 2008 and is the only library actually referenced from SQL)
CalcLibrary.dll (this is just a .NET 3.5 library that ClrIntegration.dll uses)
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)
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.
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?
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?
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.

F# WSDL code generation

I'm using VS.NET 2010 integrated shell with F# and I'm trying to consume a soap web service... How do I go about generating F# source? I tried
wsdl l:"C:\Program Files (x86)\FSharpPowerPack-2.0.0.0\bin\FSharp.Compiler.CodeDom.dll" http://localhost/?wsdl
Along with
wsdl /language:"Microsoft.FSharp.Compiler.CodeDom.FSharpCodeProvider, Microsoft.FSharp.Compiler.CodeDom, Version=1.9.2.9, Culture=neutral, PublicKeyToken=a19089b1c74d0809"
However I can't seem to get the /language switch to work.
EDIT:
taspeotis' answer got me going... This generated F# source for the web service:
gacutil -i "C:\Program Files (x86)\FSharpPowerPack-2.0.0.0\bin\FSharp.PowerPack.dll"
svcutil /language:"Microsoft.FSharp.Compiler.CodeDom.FSharpCodeProvider, FSharp.Compiler.CodeDom, Version=2.0.0.0, Culture=neutral, PublicKeyToken=a19089b1c74d0809" http://localhost/?wsdl
Have you added FSharp.Compiler.CodeDom.dll to the GAC? Use gacutil.exe to do this.
3rd party edit
Here an example gacutil.exe /l System.XML.Linq to list certain assemblies.
Besides to FSharp.Compiler.CodeDom (source) an alternative might be the FSharp.Data library
Quote from jizugu: This generated F# source for the web service:
gacutil -i
"C:\Program Files (x86)\FSharpPowerPack-2.0.0.0\bin\FSharp.PowerPack.dll"
svcutil
/language:"Microsoft.FSharp.Compiler.CodeDom.FSharpCodeProvider
,FSharp.Compiler.CodeDom, Version=2.0.0.0, Culture=neutral
,PublicKeyToken=a19089b1c74d0809" http://localhost/?wsdl
This doesn't answer your question, but you may have better luck generating C#, compiling that C# into a library DLL, and referencing that DLL from your F# code. (The C# compiler csc.exe will be part of your .NET installation.)
I would be surprised if the F# Code DOM provider worked with WSDL. I wrote the initial implementation some time ago while at Microsoft and we got it to work with ASP.NET, but unless it has been improved since then, it probably won't work with WSDL or XSD.
Even for ASP.NET, we had to create a separate class that included some ASP.NET specific "hacks". This was partly because the CodeDOM generated by ASP.NET was invalid (in a way) and because the CodeDOM structure is not quite compatible with F#. If you really need to get this to work, you may have to add similar hacks (by modifying the source from CodePlex)
I tink that a safer approach is to include a small C# library project that generates the reference for you or invoking the C# compiler using csc.exe as Brian suggests.