Assembly 'system.web, version=4.0.0.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a.' was not found in the SQL catalog
-
11-12-2020 - |
Question
I am trying to deploy a SQL CLR function using the HTTPUtility.UrlDecode method of System.Web but I can't get it to deploy. Error received:
.Net SqlClient Data Provider: Msg 6503, Level 16, State 12, Line 1 Assembly 'system.web, version=4.0.0.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a.' was not found in the SQL catalog.
The function (as part of SSDT project):
using System;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true)]
public static SqlString udf_UrlDecode(SqlString encodedXML)
{
string decodedXML;
decodedXML = HttpUtility.UrlDecode(encodedXML.ToString());
return new SqlString(decodedXML);
}
}
It's in relation to this thread. I am SQL Server 2014 with VS2012 SSDT and Database Project. Have tried with other Target Frameworks, eg 3, 3.5, 4 and 4.5.
I have also tried CREATE ASSEMBLY with System.Web, but then have to add other assemblies, eg Microsoft.Build, System.Xaml until they also fail. I see System.Web is not on the list of Supported Libraries so any ideas?
Solution
You can either use Uri.UnescapeDataString (in System
), in which case you will also need to do a Replace('+', ' ')
on the string before passing it to Uri.UnescapeDataString
, or if you would rather not bother with it, this function is available in the Free version of SQL# (which I am the author of).
Importing System.Web
is probably more work than it's worth. And in fact, it can be risky. There is a good reason that System.Web
is not in the "Supported Libraries" list that you linked to in the question: it is not guaranteed to work! You might run into situations, especially when dealing with non-US ASCII character sets, that do not behave as expected, and Microsoft will not fix it. So, unless you absolutely have to, you should be careful about adding non-supported DLLs. The DLLs in the "Supported" list have been fully tested and verified to work with SQL Server collations and any other environmental issues that are different between standard CLR running in Windows and the CLR running inside of SQL Server.
Here are some additional resources from Microsoft regarding several pitfalls to incorporating unsupported .NET Framework libraries:
A few notes about your code:
- Please do not use .NET types for parameters, input or output. Hence, change
string encodedXML
to beSqlString encodedXML
. - This function is deterministic so should be marked as such, else you will suffer a performance hit. Add
IsDeterministic = true
to theSqlFunction
attribute.
OTHER TIPS
As you have noted, System.Web
is an unsupported library. In order to reference System.Web
you will need to make a call to CREATE ASSEMBLY
. It seems like you tried that, but how did you reference the location of System.Web.dll
? Did you copy/paste it to a different location? SQL Server will try to locate dependent assemblies in the same location. In other words, if you reference the location of System.Web.dll
with all of the other dependent libraries living in the same directory, it should work just fine. Here is a working example. I was able to add both the System.Web
assembly as well as your assembly:
create assembly [System.Web]
from 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Web.dll'
with permission_set = unsafe;
go
create assembly SystemWebTest
from 'c:\SqlServer\SystemWebTest.dll'
with permission_set = safe;
go
You can see from the client messages all of the other assemblies that SQL Server loads. But take note, SQL Server displays the following warning for each of these:
you are registering is not fully tested in the SQL Server hosted environment and is not supported. In the future, if you upgrade or service this assembly or the .NET Framework, your CLR integration routine may stop working. Please refer SQL Server Books Online for more details.
Likewise, but adding System.Web
, take a look at the following assemblies that are added:
select
name,
permission_set_desc,
is_visible
from sys.assemblies
where is_user_defined = 1
order by is_visible desc;
name permission_set_desc is_visible
System.Web UNSAFE_ACCESS 1
SystemWebTest SAFE_ACCESS 1
Microsoft.Build.Framework UNSAFE_ACCESS 0
System.Xaml UNSAFE_ACCESS 0
System.ComponentModel.DataAnnotations UNSAFE_ACCESS 0
System.Runtime.Caching UNSAFE_ACCESS 0
System.Web.ApplicationServices UNSAFE_ACCESS 0
System.Drawing UNSAFE_ACCESS 0
Microsoft.Build.Utilities.v4.0 UNSAFE_ACCESS 0
System.DirectoryServices UNSAFE_ACCESS 0
System.DirectoryServices.Protocols UNSAFE_ACCESS 0
System.EnterpriseServices UNSAFE_ACCESS 0
System.Runtime.Remoting UNSAFE_ACCESS 0
System.Runtime.Serialization.Formatters.Soap UNSAFE_ACCESS 0
System.Design UNSAFE_ACCESS 0
System.Windows.Forms UNSAFE_ACCESS 0
Accessibility UNSAFE_ACCESS 0
System.Drawing.Design UNSAFE_ACCESS 0
System.Web.RegularExpressions UNSAFE_ACCESS 0
Microsoft.Build.Tasks.v4.0 UNSAFE_ACCESS 0
System.ServiceProcess UNSAFE_ACCESS 0
System.Configuration.Install UNSAFE_ACCESS 0
System.Runtime.Serialization UNSAFE_ACCESS 0
System.ServiceModel.Internals UNSAFE_ACCESS 0
SMDiagnostics UNSAFE_ACCESS 0
It is worth being mindful about what is actually happening here, and even though the other additional assemblies don't have ways for T-SQL entry points, they are now a dependency. I would weigh the options to see if you really need to reference System.Web
, or if there is another route to accomplish what you want.
Check out this answer. You don't have to use Uri.UnescapeDataString
or System.Web
. There is a class called WebUtility
inside of System.Net
with the functions HtmlEncode
and HtmlDecode
.