using System;
using System.Data.SqlClient;
using System.IO;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
namespace ScriptRunner
{
class Program
{
static void Main(string[] args)
{
var script = File.ReadAllText("Test.sql");
const string sqlConnectionString = @"Data Source=my\ds;
Initial Catalog=myic;
Connection Timeout=0;
Integrated Security=true";
SqlConnection connection = null;
Server server = null;
try
{
connection = new SqlConnection(sqlConnectionString);
server = new Server(new ServerConnection(connection));
server.ConnectionContext.BeginTransaction();
server.ConnectionContext.ExecuteNonQuery(script);
server.ConnectionContext.CommitTransaction();
}
catch { server.ConnectionContext.RollBackTransaction(); }
finally { connection?.Dispose(); }
}
}
}
The code works perfectly, except when the error is fatal.
What I mean by fatal: when inside the Test.sql, there is:
insert into TestTable (result) values ('transaction commited')
raiserror('tset', 17, -1) with log
it works - the transaction is rolled back, nothing new in TestTable
but when inside Test.sql is fatal raiserror (20):
insert into TestTable (result) values ('transaction commited')
raiserror('tset', 20, -1) with log
the insert is beeing commited to database, like there were no transaction.
This is the spinoff of question How to use transactions in SMO.Server ConnectionContext where I had fatal error in script and thought that transactions are not working at all.
The question: How to make this code handle fatal errors? Thanks.
The problem was that the fatal error is supposed to terminate process, which terminates connection. As the XACT_ABORT was not set to ON, the behaviour was as described (weird nevertheless, I'd rather expect transaction hanging..). Setting SET XACT_ABORT ON at the begining of the script fixes the problem. References: