Published on

November 24, 2023

Воссоздание файла .dll из базы данных SQL Server

Проблема: Вы импортировали сборку в базу данных 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 необходимы соответствующие права доступа к каталогу назначения.

Click to rate this post!
[Total: 0 Average: 0]

Let's work together

Send us a message or book free introductory meeting with us using button below.