Проблема: Вы импортировали сборку в базу данных SQL Server для использования содержащихся в ней функций CLR и хранимых процедур. Однако позже вы потеряли исходный файл .dll и хотите воссоздать файл .dll из содержимого базы данных. Создание скрипта сборки с использованием опции создания скрипта не помогает, потому что он создает скрипт сборки в виде двоичной последовательности, а не создает файл .dll.
Решение: Существует несколько возможностей для достижения этой цели и экспорта сборки обратно в файл .dll. В этой статье мы покажем один из возможных способов с использованием простой хранимой процедуры SQL CLR. Эта хранимая процедура принимает имя сборки и путь, где мы хотим сохранить созданный файл .dll.
Чтобы иметь возможность экспортировать сборки, нам нужно получить информацию о них и их двоичном представлении. Информация о сборках и их файлах хранится в двух системных таблицах: sys.assemblies и sys.assembly_files. Таблица sys.assemblies хранит информацию о самих сборках, такую как имя, идентификатор, набор разрешений, временную метку создания или последней модификации. Таблица sys.assembly_files содержит информацию о отдельных файлах сборки и также содержит их содержимое (двоичное представление) в поле varbinary(max).
Вот пример кода T-SQL для получения имен файлов и их двоичного содержимого для конкретной сборки:
SELECT af.name, af.content FROM sys.assemblies a INNER JOIN sys.assembly_files af ON a.assembly_id = af.assembly_id WHERE a.name = 'Microsoft.SqlServer.Types'
Мы будем использовать хранимую процедуру CLR для сохранения сборки. Сначала мы создаем новое подключение SqlConnection к SQL Server с строкой подключения “context connection=true”. Это создает новое подключение в контексте текущей сессии, из которой вызывается хранимая процедура CLR. После создания подключения мы можем создать новый SqlCommand, который выполнит вышеуказанный запрос T-SQL для получения всех имен файлов и двоичного содержимого для указанного имени сборки. В цикле мы будем перебирать все строки, возвращаемые SqlDataReader, и сохранять двоичные данные для каждого файла с использованием FileStream.
public class AssemblyExporter
{
[SqlProcedure]
public static void SaveAssembly(string assemblyName, string destinationPath)
{
// Код для получения файлов сборки и сохранения их на диск
}
}
После создания сборки AssemblyExporter мы должны создать сборку в базе данных SQL Server и создать хранимую процедуру CLR. Поскольку хранимая процедура обращается к ресурсам вне SQL Server (она сохраняет файлы сборки на диск), сборка должна быть создана с набором разрешений EXTERNAL_ACCESS, и база данных должна быть установлена в режим TRUSTWORTHY.
CREATE DATABASE [TestDB]
GO
ALTER DATABASE [TestDB] SET TRUSTWORTHY ON WITH ROLLBACK IMMEDIATE
GO
USE [TestDB]
GO
CREATE ASSEMBLY [AssemblyExporter]
AUTHORIZATION [dbo]
FROM 'C:\SQLCLR\AssemblyExporter.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS;
GO
CREATE SCHEMA [AssemblyExporter] AUTHORIZATION [dbo]
GO
CREATE PROCEDURE [AssemblyExporter].[usp_SaveAssembly] (
@assemblyName [nvarchar](128), --Имя сборки
@destinationPath [nvarchar](256) --Путь для экспорта
)
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [AssemblyExporter].[AssemblyExporter].[SaveAssembly]
GO
После создания сборки и хранимой процедуры CLR мы можем протестировать ее, передав имя сборки, которую мы хотим воссоздать, и путь, где мы хотим создать файл .dll.
EXECUTE [AssemblyExporter].[usp_SaveAssembly]
@assemblyName = 'Microsoft.SqlServer.Types',
@destinationPath = 'C:\SQLCLR'
Обратите внимание, что текущая реализация обращается к дисковому накопителю от имени учетной записи службы SQL Server. Поэтому, чтобы иметь возможность экспортировать сборку, учетной записи службы SQL Server необходимы соответствующие права доступа к каталогу назначения.