We have bunch of SQL script files that we are trying to execute via C# code.
Scenarios:
- We want to execute all the script files on SQL Server. If successfully executed all scripts then commit the transaction else rollback everything.
- If file executed successfully then log it in a table so that we will not pick it again.
- We want to keep execution for all scripts so that we can capture error if any from all the files in one go. But if any exception occur then none of the file code should get commit.
More Info: It runs well if all the script executes successfully and then Commit
works fine. However if any script in between fails then on script fail exception by default system Rollback
all scripts that were successfully executed so far and we gets a fresh connection (automatically) to execute the rest of the scripts. And after remaining each individual file which gets successful execution gets auto-commit which we do not want (because whole purpose is, commit should work only when all scripts executed successfully).
Another problem: Suppose script-2 is primary DDL
script and script-7 is DML
statement on script-2. Now if exception occurs on script-5 then system is rolling-back all scripts till 5 and we gets a new connection automatically (which we do not want, we want to have only one transaction through out). For script-6 it will work fine but for script-7 it throws error because script 7 is dependent on script 2 which is already rollback. But this is wrong. Script-2 had executed successfully and rollback forcefully on failure of script-5. So if script-5 didn't have problem then script-7 would have executed successfully. Now what we will see is error on script-7 which is consuming dev time to fix that, but there is no error at all and there could be many more such scripts.
C# Code:
public dynamic ProcessScripts(string[] files, String _sqlconString, String DatabaseName)
{
string _buildNumber = Convert.ToString(System.Configuration.ConfigurationManager.AppSettings["BuildNumber"]).Trim();
dynamic objReturn = new ExpandoObject();
objReturn.IsExceptionOccured = false;
objReturn.DBName = "";
FileInfo file = null;
bool IsExceptionOccured = false;
string script = string.Empty;
string InsertScript = string.Empty;
SqlConnection _sqlconnection = new SqlConnection(_sqlconString);
ServerConnection _ServerConnection = new ServerConnection(_sqlconnection);
Server _serverk = new Server(_ServerConnection);
_serverk.ConnectionContext.BeginTransaction();
String _QueryString = string.Empty;
foreach (string s in files)
{
file = new FileInfo(s);
String FileName = file.Name.ToLower().Trim();
script = file.OpenText().ReadToEnd();
if (script.Trim() != string.Empty)
{
try
{
InsertScript = nl+"GO "+nl+" INSERT INTO [LOGTable] (FileName,STATUS,BUILD_NO) VALUES ('" + Path.GetFileName(s.ToString()) + "','success','" + _buildNumber + "'); "+nl+"GO "+nl;
_QueryString = FindAndReplace(script) + InsertScript;
_serverk.ConnectionContext.ExecuteNonQuery(_QueryString);
WriteLog(LogType.Execution, DatabaseName, null, "Execution succeed ", FileName);
}
catch (Exception ex)
{
string _Msg = string.Empty;
if (ex.InnerException != null)
_Msg = ex.InnerException.Message;
else
_Msg = ex.Message;
WriteLog(LogType.Execution, DatabaseName, new Exception(_Msg), "Execution Failed", FileName, "");
objReturn.IsExceptionOccured = true;
}
}
}
if (objReturn.IsExceptionOccured)
{
_serverk.ConnectionContext.RollBackTransaction();
}
else
{
_serverk.ConnectionContext.CommitTransaction();
}
return objReturn;
}