T-SQL не может найти функцию CLR в сборке - нет пространства имен?

Мы портируем базу данных SQL Server, которая включает сборку CLR с функциями даты (разработчик давно ушел). Я создал сборку из DLL (она указана в sys.assemblies):

CREATE ASSEMBLY ArkaDB FROM 'C:\Temp\ArkaDB.dll' WITH PERMISSION_SET = SAFE;

Но когда я пытаюсь создать хранимую процедуру SQL для функции GetOIDate:

create FUNCTION [dbo].[GetOIDate](@ActivityDate [datetime])
RETURNS [datetime] WITH EXECUTE AS CALLER
AS 
EXTERNAL NAME [ArkaDB].[ArkaDB.UserDefinedFunctions].[GetOIDate]

выдает ошибку «Сообщение 6505, уровень 16, состояние 2, процедура GetOIDate, строка 2. Не удалось найти тип ArkaDB.UserDefinedFunctions в сборке ArkaDB».

Вы можете увидеть структуру DLL вместе с кодом функции на снимке экрана ILSpy ниже. Обратите внимание на дефис "-" для пространства имен. Из этого вопроса мы должны включить пространство имен в спецификацию EXTERNAL NAME. Но что, если нет пространства имен? Ответ здесь указывает, что вы просто предоставляете класс, например "ВНЕШНЕЕ ИМЯ [ SqlClr].Math.[Добавить]". Я пробовал все возможные варианты, и все они дают одну и ту же ошибку «не удалось найти»:

EXTERNAL NAME [ArkaDB].[ArkaDB.UserDefinedFunctions].[GetOIDate]
EXTERNAL NAME [ArkaDB].UserDefinedFunctions.[GetOIDate]
EXTERNAL NAME [ArkaDB].[.UserDefinedFunctions].[GetOIDate]
EXTERNAL NAME [ArkaDB].[-.UserDefinedFunctions].[GetOIDate]
EXTERNAL NAME [ArkaDB].[''.UserDefinedFunctions].[GetOIDate]
EXTERNAL NAME [ArkaDB].[ .UserDefinedFunctions].[GetOIDate]

Любые идеи? Мы используем SQL Server 2012, а DLL изначально была разработана и установлена ​​в 2008 R2. ILSpy для ArkaDB DLL

Изменить: для srutzky вот определение общедоступного класса в классе ILSpy UserDefinedFunctions


person user906802    schedule 20.06.2017    source источник
comment
Это -- EXTERNAL NAME [ArkaDB].UserDefinedFunctions.[GetOIDate] -- должно быть правильным, или вы можете добавить квадратные скобки вокруг имени класса: EXTERNAL NAME [ArkaDB].[UserDefinedFunctions].[GetOIDate]. Этот класс помечен как общедоступный?   -  person Solomon Rutzky    schedule 21.06.2017
comment
Спасибо за ответ. Да, класс является общедоступным — см. изображение, добавленное к сообщению выше. Вы правы в том, что формат должен быть правильным. Если я создаю сценарий функции SQL в старой базе данных, она генерирует ВНЕШНЕЕ ИМЯ [ArkaDB].[UserDefinedFunctions].[GetOIDate]. Однако это дает аналогичную ошибку при запуске на новом сервере. Не удалось найти тип «UserDefinedFunctions» в сборке «ArkaDB». Мой следующий шаг — попытаться пересобрать DLL в Visual Studio, но это всегда чревато для устаревшего кода: есть ли у меня правильный исходный код? Есть ли проблемы с версией VS?   -  person user906802    schedule 22.06.2017
comment
Совпадают ли ваши имена с именами из таблиц sys.assembl*? Как описано здесь: docs.microsoft. com/en-us/sql/t-sql/statements/ Найдите на странице sys.   -  person shibormot    schedule 22.06.2017
comment
Просто предположение, но можете ли вы попробовать использовать DATETIME2 вместо DATETIME для типов входных параметров и возвращаемых значений?   -  person Solomon Rutzky    schedule 22.06.2017
comment
Вы на 100% уверены, что DLL, которую вы загрузили в SQL Server 2012, точно такая же, которая использовалась для загрузки 2008 R2? Вы должны сравнить значения, найденные в столбце content, используя следующий запрос: SELECT DATALENGTH([content]) AS [bytes], * FROM sys.assembly_files WHERE [name] LIKE N'%ArkaDB%' AND [file_id] = 1;. Если они имеют одинаковое количество байтов, вам необходимо сравнить содержимое. Вы можете скопировать и вставить значения содержимого с обоих серверов в запрос, где вы создадите их как переменные VARBINARY(MAX) или VARCHAR(MAX) и посмотрите, равны ли они.   -  person Solomon Rutzky    schedule 22.06.2017


Ответы (1)


К сожалению, я не могу комментировать (недостаточно репутации), поэтому давайте попробуем вместо этого ответить:

Вы писали: "Если я создаю скрипт функции SQL в старой базе данных, она генерирует "ВНЕШНЕЕ ИМЯ [ArkaDB].[UserDefinedFunctions].[GetOIDate]".". Что, если вы создадите сценарий сборки из старой базы данных (я полагаю, где она работает) и развернете таким образом новую базу данных.

Что-то типа:

CREATE ASSEMBLY ArkaDB FROM binary_representation WITH PERMISSION_SET = SAFE;

Таким образом, вы, по крайней мере, сможете его развернуть. Если в вашей сборке не существует пространства имен, функция создания должна быть такой, как говорит srutzky:

CREATE FUNCTION [dbo].[GetOIDate](@ActivityDate [datetime])
RETURNS [datetime] WITH EXECUTE AS CALLER
EXTERNAL NAME [ArkaDB].[UserDefinedFunctions].[GetOIDate]

Дайте нам знать, пожалуйста, как это происходит.

Нильс

person Niels Berglund    schedule 02.07.2017