У меня есть таблица в базе данных SQL Server со столбцом varbinary(max) с zip-архивами. Как мне получить список этих архивов, не распаковывая их? Мое приложение C# читает список этих архивов, и мне нужно добавить дополнительную информацию о содержимом.
Для файла я использую класс ZipFile из сборки System.IO.Compression.FileSystem, но как передать данные varbinary вместо имени файла (например, если я создаю функцию CLR)?
Вы не можете без разархивирования файла. SQL Server не имеет метода распаковки, поэтому вам придется создать хранимую процедуру или использовать внешний инструмент. Я бы использовал утилиту SQL SQLCMD.EXE и создал бы свой собственный инструмент для получения имен файлов.
Почему бы просто не сохранить список файлов в отдельном столбце varchar (max) вдоль zip-потока?
1) в этом случае при загрузке файла мне нужно добавить этот список файлов программно, 2) или мне нужен триггер, который бы каким-то образом определял содержимое (и все то же самое - как это сделать без извлечения в базу данных) ? Я хочу динамически получать содержимое архива.





Это то, что вы ищите?
SQLCLR C# функция ...
using System.Data.SqlTypes;
using System.IO;
using System.IO.Compression;
using System.Linq;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString ZipEntries(SqlBytes data) {
using (var stream = new MemoryStream(data.Value))
using (var archive = new ZipArchive(stream))
return new SqlString(string.Join(",", archive.Entries.Select(e => e.Name)));
}
}
Вот SQL, который я использовал для тестирования. Удивительно, но это сработало ...
-- Create table with ZIP archive column...
CREATE TABLE dbo.ZipImages(ZipArchive VARBINARY(MAX));
GO
-- ... then insert ZIP archive content into the dbo.ZipImages table ...
-- (code not included)
GO
-- ... then prove it works.
SELECT dbo.ZipEntries(ZipArchive) FROM dbo.ZipImages;
GO
Возможно / вероятно, что ваша база данных будет скулить о том, что System.IO.Compression недоступен, и в этом случае вы можете попробовать ...
ALTER DATABASE [<your database>] SET TRUSTWORTHY ON;
CREATE ASSEMBLY [System.IO.Compression]
FROM N'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.IO.Compression.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS;
(Если вы не администратор базы данных, вам захочется быстро завести друзей.)
Очевидно, это просто UDF - вы, вероятно, захотите сделать что-то немного другое (например, сделать его UDF CLR на основе таблицы, чтобы возвращать записи одну за другой).
Если вам нужно открыть файлы из архива в столбце данных, это становится сложнее. Помимо прочего, вам нужно будет добавить System.IO.Compression.File в качестве сборки, что (к сожалению) НЕ БЕЗОПАСНО и усложняет кучу вещей ...
CREATE ASSEMBLY [System.IO.Compression.FileSystem]
FROM N'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.IO.Compression.FileSystem.dll'
WITH PERMISSION_SET = UNSAFE;
Вместо этого используйте ZipArchive, чтобы передать поток.