【发布时间】:2015-10-12 18:41:39
【问题描述】:
当我尝试从 SQL Server 2008 R2 执行 C# CLR 存储过程时出现以下错误:
消息 6522,级别 16,状态 1,过程 PrintShippingDocLabelsToPDF,第 0 行
在执行用户定义的例程或聚合“PrintShippingDocLabelsToPDF”期间发生 .NET Framework 错误:
System.InvalidOperationException:无法加载动态生成的序列化程序集。在某些托管环境中,程序集加载功能受到限制,请考虑使用预生成的序列化程序。请参阅内部异常了解更多信息。 --->
System.IO.FileLoadException:LoadFrom()、LoadFile()、Load(byte[]) 和 LoadModule() 已被主机禁用。
System.IO.FileLoadException:
据我了解,这正是因为我试图 写入网络共享上的文件。我查看了以下来源:https://msdn.microsoft.com/en-us/library/ms345106(v=sql.105).aspx、Accessing Sql FILESTREAM from within a CLR stored procedure,但我仍然迷路了。
我需要做的就是将几个报告从 SSRS 写入网络共享上的 xxx.pdf 文件(其中 xxx 代表自定义名称)。此功能的代码如下,我相当肯定下面的部分会导致错误。
// Create a file stream and write the report to it
using (FileStream stream = File.OpenWrite(strFilePath + strFileName))
{
stream.Write(results, 0, results.Length);
} // END using (FileStream stream = File.OpenWrite(StoredProcedures.strFilePath + StoredProcedures.strFileName))
这是完整的过程。有人可以给我指点吗?我的工作期限很紧。作为临时解决方案,也许可以将这些报告写入临时表,然后使用 SSIS 包将它们移动到文件夹中。如果可能的话,有人可以告诉我如何存储这些文件(varbinary(这些文件的最大大小约为 60KB-150KB)?
public static void PrintShippingDocLabelsToPDF()
{
// Put your code here
using (SqlConnection sqlConnTestDB = new SqlConnection("context connection=true"))
{
string sql4ConnectionString = "connection string";
string sqlConnStrTestDB = sql4ConnectionString;
// Select all unprinted SPSNumbers
// If IsValidatedByWms == 0 --> SPS Not printed
// If IsValidatedByWms == 1 --> SPS is printed
string sqlCmdSlctTblPicking = @"SELECT SPSNumber, IsValidatedByWms AS LabelPrintStatus
FROM TestDB.dbo.tblPickingSlip WHERE IsValidatedByWms = 0";
//SqlConnection sqlConnTestDB = new SqlConnection(sqlConnStrTestDB);
SqlCommand sqlCmdSlctPicking = new SqlCommand(sqlCmdSlctTblPicking, sqlConnTestDB);
// Select all SPSNumbers that have invoices against them
// SPS number will be coming from tblPicking
// If SPSNumber is NULL --> No invoice against SPS
// If SPSNumber is NOT NULL --> There is an invoice against the SPS
string sqlCmdStrSlctTblInvoiceItem = @"SELECT DISTINCT SPSNumber
FROM TestDB.dbo.tblInvoiceItem
WHERE SPSNumber IS NOT NULL ";
SqlCommand sqlCmdSlctTblInvoiceItem = new SqlCommand(sqlCmdStrSlctTblInvoiceItem, sqlConnTestDB);
DataTable dtPicking = new DataTable();
SqlDataAdapter sqlPickingAdapter = new SqlDataAdapter(sqlCmdSlctPicking);
sqlPickingAdapter.Fill(dtPicking);
DataTable dtTblInvoiceItem = new DataTable();
SqlDataAdapter sqlTblInvoiceItemAdapter = new SqlDataAdapter();
// Update print status of printed lables, labels only print for SPSNumbers that have invoices against them
string sqlCmdStrUpdate = @"UPDATE TestDB.dbo.tblPickingSlip
SET IsValidatedByWms = 1
WHERE SPSNumber = ";
SqlCommand sqlCmdUpdateSlctPicking = new SqlCommand(sqlCmdStrUpdate, sqlConnTestDB);
string strSpsNumber = null; // keep track of the SPSNumber
// Inspect the Picking table
foreach (DataRow row in dtPicking.Rows)
{
if (Convert.ToInt32(row["LabelPrintStatus"]) == 0)
{
// a label has not been printed for the associated SPSNumber
// check if the particualr SPSNumber has an assocaited invoice
strSpsNumber = row["SPSNumber"].ToString();
// add SPSNumber to query that selects all SPSNumbers that
// have invoices against them
string sqlCmdStrSlctTblInvoiceItem2 = sqlCmdStrSlctTblInvoiceItem + "AND SPSNumber = '" + strSpsNumber + "'";
sqlCmdSlctTblInvoiceItem.CommandText = sqlCmdStrSlctTblInvoiceItem2;
sqlTblInvoiceItemAdapter.SelectCommand = sqlCmdSlctTblInvoiceItem;
sqlTblInvoiceItemAdapter.Fill(dtTblInvoiceItem);
// Inspect tblInvoiceItem and print all SPSNumbers that have invoices against them
if (dtTblInvoiceItem != null)
if (dtTblInvoiceItem.Rows.Count > 0)
{
foreach (DataRow r in dtTblInvoiceItem.Rows)
{
// Write the report to the ExportFilePath
//WriteReport(strSpsNumber);
string ExportFilePath = @"\\testsrv\EXPORT\"; // locaiton where PDF reports will be written.
string ReportPath = @"/xxx/Report1"; // Path to report on modabackupsql reportserver
string FileExtentionPDF = @".pdf";
PrintShippingDocLabelPDF.REService2005.ReportExecutionService _re; // proxy class for the report execution for
// Report arguments
string report = ReportPath;
string historyID = null;
string deviceInfo = null;
string format = @"PDF";
Byte[] results;
string encoding = String.Empty;
string mimeType = String.Empty;
string extension = String.Empty;
PrintShippingDocLabelPDF.REService2005.Warning[] warnings = null;
string[] streamIDs = null;
string strFilePath = ExportFilePath; // location for writing PDF labels generated from executed reports
string strFileName; // the name of pdf labels generated from executed reports
_re = new PrintShippingDocLabelPDF.REService2005.ReportExecutionService();
_re.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Prepare Render arguments
PrintShippingDocLabelPDF.REService2005.ExecutionInfo ei = _re.LoadReport(report, historyID);
PrintShippingDocLabelPDF.REService2005.ParameterValue[] parameters = new PrintShippingDocLabelPDF.REService2005.ParameterValue[1];
// add the spsnumber as the report parameter
parameters[0] = new PrintShippingDocLabelPDF.REService2005.ParameterValue();
parameters[0].Name = "spsnumber";
parameters[0].Value = strSpsNumber;
strFileName = strSpsNumber + FileExtentionPDF;
// set the execution parameters
_re.SetExecutionParameters(parameters, "en-us");
// render the report
results = _re.Render(format, deviceInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
// Create a file stream and write the report to it
using (FileStream stream = File.OpenWrite(strFilePath + strFileName))
{
stream.Write(results, 0, results.Length);
} // END using (FileStream stream = File.OpenWrite(StoredProcedures.strFilePath + StoredProcedures.strFileName))
// Set the IsValidatedByWms associated with SPSNumber to 1
// to indicate that the report has been printed.
//sqlConnTestDB.Open();
sqlCmdUpdateSlctPicking.CommandText = sqlCmdStrUpdate + "'" + strSpsNumber + "'";
sqlCmdUpdateSlctPicking.ExecuteNonQuery();
//sqlConnTestDB.Close();
} // END foreach (DataRow r in dtTblInvoiceItem.Rows)
dtTblInvoiceItem.Clear();
} // if (dtTblInvoiceItem.Rows.Count > 0)
} // END if (Convert.ToInt32(row["LabelPrintStatus"]) == 0)
} // END foreach (DataRow row in dtPicking.Rows)
} // END using (SqlConnection sqlConnTestDB = new SqlConnection("context connection=true"))
} // END public static void PrintShippingDocLabelsToPDF()
【问题讨论】:
-
如果您尝试写入托管 SQL Server 的机器上的本地文件夹,这可以正常工作吗?
-
嗨 Sven,代码在 CLR 之外工作(即它在控制台应用程序中工作,从那里我可以建立到服务器的连接运行我的查询并将报告写入文件系统,这一切都停止了当我将代码移动到 CLR 时工作)。共享实际上位于托管 SQL 的盒子上,因此,本质上它是一个本地文件夹。
-
您使用什么权限注册了您的 CLR?您是否将您的数据库标记为 TRUSTWORTHY 并将您的程序集标记为 UNSAFE?如果不熟悉这些权限,请参阅MSDN。
-
错误不是来自您的代码,因为您没有加载文件,而是尝试保存文件。我猜这个错误来自
ReportExecutionService。这是使用网络服务吗? -
我试图在 Visual Studio 2010 项目选项中使该过程不安全,但部署失败。我不知道如何将数据库标记为值得信赖的还没有看到这个。
标签: c# sql-server-2008-r2 sqlclr