2

I have a SQLCLR Function that serializes an object as XML that works fine on my local development machine (and our other DBA's machine as well), but when I try and run the same function on our test database server, I get the following:

Msg 6522, Level 16, State 1, Line 1
A .NET Framework error occurred during execution of user-defined routine or aggregate "GetXml":
System.InvalidOperationException: 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.

System.IO.FileLoadException: LoadFrom(), LoadFile(), Load(byte[]) and LoadModule() have been disabled by the host.
System.IO.FileLoadException:
at System.Reflection.RuntimeAssembly.nLoadImage(Byte[] rawAssembly, Byte[] rawSymbolStore, Evidence evidence, StackCrawlMark& stackMark, Boolean fIntrospection, SecurityContextSource securityContextSource)
at System.Reflection.Assembly.Load(Byte[] rawAssembly, Byte[] rawSymbolStore, Evidence securityEvidence)
at Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(CompilerParameters options, String[] fileNames)
at Microsoft.CSharp.CSharpCodeGenerator.FromSourceBatch(CompilerParameters options, String[] sources) at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, String[] sources) at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence) System.InvalidOperationException: at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence) at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies) at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace) at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace) at XmlExtensions.ToXml[T](T value) at UserDefinedFunctions.GetXml()

I have seen a lot of posts that say that you need to create a Assembly.XmlSerializers.dll, but if that's really the case, why does it work fine on our local machines without needing that DLL?

In order to make sure it wasn't something related to compiling the same code, I created a new SQL project, compiled it, and then just sent the SQL script to our DBA and he was able to run it without needing the XmlSerializers.dll.

using System;
using System.Data.SqlTypes;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.SqlServer.Server;

public class UserDefinedFunctions
{
    [SqlFunction(IsDeterministic = true, DataAccess = DataAccessKind.Read)]
    public static SqlXml GetXml()
    {
        var x = new Test1 { S = DateTime.Now.ToString() };
        return new SqlXml(new XmlTextReader(x.ToXml(), XmlNodeType.Document, null));
    }
}

public class Test1
{
    public string S { get; set; }
}

public static class XmlExtensions
{
    public static string ToXml<T>(this T value)
    {
        if (value == null) return string.Empty;

        var xmlserializer = new XmlSerializer(typeof(T));

        using (StringWriter stringWriter = new StringWriter())
        {
            using (var writer = XmlWriter.Create(stringWriter, new XmlWriterSettings { Indent = true }))
            {
                xmlserializer.Serialize(writer, value);
                return stringWriter.ToString();
            }
        }
    }
}

The dacpac from this project loaded fine on the other developer's machine, but failed for the same reason on our test server. I haven't found anything telling me why this would work on some machines but not on others.

Solomon Rutzky
  • 46,688
  • 9
  • 128
  • 171
randomsolutions
  • 2,075
  • 1
  • 19
  • 22
  • 1
    What version of SQL Server are you using? Your machine, the DBA's, and the Test server? – Solomon Rutzky Feb 16 '16 at 23:50
  • @srutzky - Microsoft SQL Server 2012 SP3 on all machines (11.0.6020). – randomsolutions Feb 17 '16 at 00:20
  • 1
    I am unable to get this code to error. I tested on 2012 SP 2 (LocalDB and Developer Edition) and 2014 SP 1. Given that your dev machine, the DBAs local machine, and my local machine all work, yet the server does not, this might be an issue of the server not having the proper .NET Framework updates. Can you check to see if it has been patched with the more recent .NET Frameworks, 4.0 and newer? Obviously it has 4.0, but my machine has had 4.5, 4.5.2, and now has 4.6. Check your machine, the DBAs, and the Test servers .NET Framework in the 4.x series. If not that, maybe a group security policy? – Solomon Rutzky Feb 17 '16 at 01:32
  • 1
    @srutzky - Our test servers only had .NET 4.0 on them vs 4.6 on our machines. When I updated the .NET framework, the problem went away. If you write up your comment as an answer, I'll mark it as answered. I appreciate your help! – randomsolutions Feb 17 '16 at 18:19
  • Woo hoo! glad it worked :-). I was waiting to hear back before typing anything up because it was just an educated guess. Of course, I suppose maybe we should have first tried targeting the 4.0 Framework first to see if that alone would help, but I also see no downside to having the latest Framework version on the servers (all machines, really). – Solomon Rutzky Feb 17 '16 at 18:28

1 Answers1

1

I also tested this same code on my laptop and could not get it to error. So here is what we know:

It does work on:

  • Dev's local machine running SQL Server 2012 SP3.
  • DBA's local machine running SQL Server 2012 SP3.
  • My laptop running SQL Server 2012 SP 2 (LocalDB and Developer Edition) and SQL Server 2014 SP 1 (LocalDB).

It does NOT work on:

  • The Test server running SQL Server 2012 SP3.

Given that your dev machine, the DBA's local machine, and my local machine all work, yet the server does not, this might be an issue of the server not having the proper .NET Framework updates installed.

Check to see if the Test server has been patched with the more recent .NET Frameworks, 4.0 and newer. Obviously it has 4.0 as that would be installed when installing SQL Server 2012 if it wasn't already there, but my machine has had 4.5, 4.5.2, and now has 4.6. Check your machine, the DBAs, and the Test servers .NET Framework in the 4.x series.

P.S. If you aren't doing a SELECT via SqlConnection, then don't set DataAccess = DataAccessKind.Read in the SqlFunction attribute. It is a performance hit that you don't want unless you are actually reading data from SQL Server. The default is DataAccessKind.None.

UPDATE from the O.P.

Our test servers only had .NET 4.0 on them vs 4.6 on our machines. When I updated the .NET framework, the problem went away.

Solomon Rutzky
  • 46,688
  • 9
  • 128
  • 171