我要做的是在SSIS中创建一个框架,以动态生成制表符分隔的UTF8文本文件。数据源是SQL Server,要输出的查询存储在物理数据库表中,SQL查询和一些其他参数(例如文件输出位置)通过变量传递给SSIS脚本任务。然后执行查询,然后将结果流式传输到指定位置。
这部分工作正常 - 但是当我尝试引入异常处理时,我开始遇到一些问题。如果源SQL中存在错误,我希望抛出异常并将SQL Server错误消息插回到源表中。再次,我使用SqlException类使这个工作。但是,根据SQL错误,可能生成也可能不生成空白的0字节文本文件。例如,源SQL中的语法错误将直接抛出到catch块,但除以0错误会创建一个空白的0字节文本文件。在这两种情况下,源表都会更新错误。我怎么能避免这个?无论错误是什么,我都不希望生成文件。
这就是我拼凑在一起的...我是C#的菜鸟,这是我第一次尝试C#编码,所以如果这里有明显的男生错误,或者我有办法改善这一点,我如果你能指出这些,我将不胜感激!
由于
/*
Microsoft SQL Server Integration Services Script Task
Write scripts using Microsoft Visual C# 2008.
The ScriptMain is the entry point class of the script.
*/
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.IO;
using System.Text;
//using System.Data.SqlClient;
namespace ST_5f2e36fd61064ad8ae13e81d97fe899e.csproj
{
[System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
#region VSTA generated code
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
#endregion
public void Main()
{
//establish connection to data source using ADONET connection manager
SqlConnection myADONETConnection = new SqlConnection();
myADONETConnection = (SqlConnection)(Dts.Connections["ADONET"].AcquireConnection(Dts.Transaction) as SqlConnection);
//variable declarations
int ReportId = (int)Dts.Variables["ReportId"].Value;
bool ExportColumnNames =(bool) Dts.Variables["ExportColumnNames"].Value;
string SQLQuery = Dts.Variables["Query"].Value.ToString();
string strFilePath = "\\\\" + Path.Combine(Path.Combine(Dts.Variables["OutputServerName"].Value.ToString(), Dts.Variables["OutputFilepath"].Value.ToString()), Dts.Variables["OutputFilename"].Value.ToString());
string strColumnNames = "";
SqlDataReader reader;
using (myADONETConnection)
{
try
{
using (reader = new SqlCommand(SQLQuery, myADONETConnection).ExecuteReader())
{
//get the column names from the query into a string variable
//or use DataTable instead? which is better?
for (int col = 0; col < reader.FieldCount; col++)
{
strColumnNames += reader.GetName(col).ToString() + "\t";
}
// remove final \t from strColumnName string
strColumnNames = strColumnNames.Remove(strColumnNames.Length - 1);
using (StreamWriter writer = new StreamWriter(strFilePath)) //creates file; also creates 0 byte file on divide by 0 SQL error...
{
//insert column names (only if flag on table is set to true)
if (ExportColumnNames == true)
{
writer.WriteLine(strColumnNames);
}
//insert data
while (reader.Read())
{
//if (reader.HasRows)
//{
StringBuilder sb = new StringBuilder(reader[0].ToString());
for (int i = 1; i < reader.FieldCount; i++)
{
sb.AppendFormat("\t{0}", reader[i]);
} //end for
writer.WriteLine(sb.ToString());
//} //end if
} //end while
} //end (using streamwriter)
//reader.Close();
} //end (using reader) (closes the reader)
//update source table as success
var command = new SqlCommand("UPDATE tblAnalyticsFrameworkControlTable SET ExportDate = GETDATE(), ExportSuccessful = 1 WHERE ID = @ID", myADONETConnection);
SqlParameter ID = new SqlParameter();
ID.ParameterName = "@ID";
ID.Value = ReportId;
command.Parameters.Add(ID);
command.ExecuteNonQuery();
myADONETConnection.Close();
} //end try
catch (SqlException ex)
{
//insert error message back to table
var command = new SqlCommand("UPDATE tblAnalyticsFrameworkControlTable SET ExportDate = GETDATE(), ExportSuccessful = 0, ExportErrorMessage = @ErrorMessage WHERE ID = @ID", myADONETConnection);
SqlParameter ErrorMessage = new SqlParameter();
ErrorMessage.ParameterName = "@ErrorMessage";
ErrorMessage.Value = ex.Message;
command.Parameters.Add(ErrorMessage);
SqlParameter ID = new SqlParameter();
ID.ParameterName = "@ID";
ID.Value = ReportId;
command.Parameters.Add(ID);
command.ExecuteNonQuery();
//remove blank file created by StreamWriter method (preferably without removing pre-existing valid files if possible!)
File.Delete(strFilePath);
} //end catch
Dts.TaskResult = (int)ScriptResults.Success;
}
}
}
}