在 .NET 應用程式中執行 T-SQL 指令碼檔

當你在 .NET 應用程式,使用 ADO.NET 提交包含 GO 指令的 T-SQL 批次時,SQL Server 會引發的語法不正確的錯誤。這是因為 GO 指令是 sqlcmd 、osql 等公用程式和 SQL Server 指令碼編輯器所認識的指令,而非有效的 T-SQL 陳述式。

在執行含有一個以上 T-SQL 批次的指令碼時,SQL Server 公用程式會將 GO 視為 T-SQL 陳述式批次結束的信號,並將目前一個或多個 SQL 陳述式的集合傳送至 SQL Server,但並不包含 GO 指令。因此,當你使用 ADO.NET 執行多個 T-SQL 批次的指令碼時,你必須自行過濾 GO 指令,並分批執行 T-SQL 陳述式。

如以下範例使用 EmbeddedResourceTextReader 讀取內嵌資源的 SQL 指令碼檔內容,並透過 Regex 物件以 GO 關鍵字將指令碼分隔成批次陳述式,然後再逐一提交至 SQL Server 執行:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Text.RegularExpressions;

namespace RunSql
{
class Program
{
static void Main(string[] args)
{
string script = new EmbeddedResourceTextReader()
.GetFromResources("RunSql.Install.sql");

string[] stmts = Regex.Split(script, "\\sGO\\s", RegexOptions.IgnoreCase);

using (SqlConnection conn =
new SqlConnection(ConfigurationManager
.ConnectionStrings["DefaultConnection"]
.ConnectionString))
{
conn.Open();
using (SqlTransaction trans =
conn.BeginTransaction(IsolationLevel.ReadUncommitted))
{
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.Transaction = trans;
cmd.CommandType = CommandType.Text;

foreach (string stmt in stmts)
{
cmd.CommandText = stmt.Trim();
if (cmd.CommandText.Length > 0)
{
try
{
cmd.ExecuteNonQuery();
}
catch(SqlException)
{
trans.Rollback();
throw;
}
}
}
}
trans.Commit();
}
}
}
}
}

相較於 ADO.NET,使用 SQL Server Management Objects(SMO)就無須處理 GO 指令的問題,使用起來更為簡便。有關如何使用 SMO 執行 T-SQL 批次的範例程式碼,請參閱這裡


Share/Save/Bookmark

0 comments :: 在 .NET 應用程式中執行 T-SQL 指令碼檔

張貼留言