【问题标题】:Can't add System.IO.Compression to trusted assemblies in SQL Server无法将 System.IO.Compression 添加到 SQL Server 中的受信任程序集
【发布时间】:2014-09-10 04:24:51
【问题描述】:

我正在尝试在 NET 4.5 中创建一个 SQLCLR 存储过程来处理 ZIP 文件。显然System.IO.Compression 不在 SQL Server 的批准列表中,但这是我尝试通过 SQL Server Management Studio 手动添加它时得到的。如果我尝试通过查询执行CREATE ASSEMBLY,也会发生同样的情况。有任何想法吗?为什么这是一个禁忌?

我也试过在 SSMS 中运行这个命令:

CREATE ASSEMBLY SystemIOCOMPRESSION
  FROM 'C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\System.IO.Compression.dll'
  WITH PERMISSION_SET = EXTERNAL_ACCESS

...结果与我通过 SSMS UI 尝试的结果相同。

【问题讨论】:

  • 您是否尝试过将 EXTERNAL_ACCESS 与 CREATE ASSEMBLY 一起使用?你能添加产生错误的代码吗?
  • 是的,我确实尝试过,但它与我在 UI 中尝试的其他东西基本相同。问题已更新。
  • 您可能需要在添加程序集之前ALTER DATABASE dbname SET TRUSTWORTHY ON;。我刚刚尝试了这个并且得到了一堆 CLR 验证器错误,所以这可能不会让你一路走好。
  • 另外,你试图让 SQL Server 处理这个程序集做什么?如果您尝试存储压缩数据,为什么不使用 SQL Server 原生压缩?
  • TRUSTWORTHY ON 已经设置好了,所以不是这样。顺便说一句,我需要做一些压缩工作,而不仅仅是使用本机压缩存储压缩数据。

标签: c# .net sql-server ssms sqlclr


【解决方案1】:

您正在尝试导入错误的 DLL。那是“参考”DLL,而不是实际的“框架”DLL。以下将起作用,因为我不仅使用 SQL Server 2012 进行了尝试,而且还能够导入 System.IO.Compression.FileSystem 并执行 System.IO.Compression.ZipFile.CreateFromDirectory()

  1. 这是必需的,因为您无法从 .Net Framework DLL 创建 ASYMMETRIC KEY

    ALTER DATABASE [{dbname}] SET TRUSTWORTHY ON;
    
  2. 至少你需要这个:

    CREATE ASSEMBLY [System.IO.Compression]
    FROM N'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.IO.Compression.dll'
    WITH PERMISSION_SET = EXTERNAL_ACCESS;
    
  3. 如果您想使用ZipFileZipFileExtensions 类,您将需要这个(不幸的是,这个需要设置为UNSAFE):

    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;
    
  4. 以防万一,调用上述程序集中方法的程序集还需要有PERMISSION_SETEXTERNAL_ACCESS

  5. 对于任何可能不知道这一点的人来说,这是完全清楚的:

    1. Zip* 类以及 System.IO.CompressionSystem.IO.Compression.FileSystem 程序集是 .Net 4.5 的新功能
    2. 您只能在 SQL Server 2012 和 2014(当前版本)中使用 .Net 4.0 / 4.5 的新项目; SQL Server 2005 / 2008 / 2008 R2 卡在 .Net 2.0 系列上。

【讨论】:

  • 谢谢!我对此失去了兴趣,但总的来说它看起来不错。当我再次遇到这个时,我一定会尝试一下。
【解决方案2】:

我知道这是一个老问题,但是本周早些时候我在写一个 SQLCLR 函数,生成报告后可以由 ssrs sql 代码调用,将它们打包成一个 zip 文件并通过电子邮件发送给它们给用户。

经过大量研究和反复试验,使用 ssrs Web 服务接口是更简单、更合理的方法。您根本不必触摸数据库设置即可使用它并执行完全相同的操作。

要使用它,您需要添加对 ssrs 执行服务的 Web 引用。您可以通过need here 找出您是哪一个。配置并添加 Web 引用后,您可以编写 C#/VB 代码,以您选择的格式将您想要的任何报告呈现为字节,然后像任何其他字节流一样保存它们或按照您的意愿使用它们。在我们的例子中,我们编写了一个查询来获取用户发送的报告列表,使用 api 将该用户的所有报告呈现到临时文件,压缩这些临时文件,将它们附加到电子邮件中,然后发送电子邮件关闭给用户。

有一个很好的简单示例,说明如何使用 api here 呈现报表并将其保存到磁盘。 (下面的代码以防链接失效)

string historyID = null;
string deviceInfo = null;
// Can be XML, NULL, CSV, IMAGE, PDF, HTML4.0, HTML3.2,
// MHTML, EXCEL, and HTMLOWC
string format = "Excel"; 
Byte[] results;
string encoding = String.Empty;
string mimeType = String.Empty;
string extension = String.Empty;
ReportingExec.Warning[] warnings = null;
string[] streamIDs = null;


ReportingExec.ReportExecutionService re = new ReportingExec.ReportExecutionService();
re.Credentials = System.Net.CredentialCache.DefaultCredentials;

ReportingExec.ExecutionInfo ei = re.LoadReport("/directory/ReportName", historyID);

ReportingExec.ParameterValue[] rptParameters = new ReportingExec.ParameterValue[1];

rptParameters[0] = new ReportingExec.ParameterValue();
rptParameters[0].Name = "DateFormatID";
rptParameters[0].Value = "fr-FR";

re.SetExecutionParameters(rptParameters, "en-us");


results = re.Render(
    format, deviceInfo, out extension, out encoding, 
    out mimeType, out warnings, out streamIDs);

FileStream stream = File.Create("C:\\report.xls", results.Length);
stream.Write(results, 0, results.Length);
stream.Close();

一开始让我感到困惑的是,在哪里可以找到上述各种类型。当您将 Web 引用添加到您的项目时,Web 引用将在以您提供 Web 引用的名称命名的命名空间中拉入所有必要的类型。因此,如果您将 Web 引用命名为 FooService,则所有报告类型都将位于命名空间 FooService 中。所以你可以在那里找到FooService.ParameterValueFooService.ReportExecutionService等。

【讨论】:

    猜你喜欢
    • 2018-02-27
    • 2010-09-30
    • 2021-06-13
    • 2017-09-18
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多