Сбой транзакции SMO через код C#
У нас есть куча файлов сценариев SQL, которые мы пытаемся выполнить с помощью кода C#.
Сценарии:
- Мы хотим выполнить все файлы сценариев на SQL Server. Если все сценарии успешно выполнены, зафиксировать транзакцию, иначе откатить все.
- Если файл успешно выполнен, зарегистрируйте его в таблице, чтобы мы не выбрали его снова.
- Мы хотим сохранить выполнение для всех сценариев, чтобы мы могли зафиксировать ошибку, если она есть, из всех файлов за один раз. Но если произойдет какое-либо исключение, ни один из файловых кодов не получит фиксацию.
Больше информации: Хорошо работает, если все сценарии выполняются успешно, а затем Commit
работает отлично. Однако, если какой-либо сценарий между ними завершится неудачно, то при возникновении ошибки сценария по умолчанию система Rollback
все сценарии, которые были успешно выполнены до сих пор, и мы получаем новое соединение (автоматически) для выполнения остальных сценариев. И после оставления каждого отдельного файла, который получает успешное выполнение, происходит автоматическая фиксация, которая нам не нужна (поскольку в целом цель - фиксация должна работать только тогда, когда все сценарии выполнены успешно).
Еще одна проблема: предположим, что скрипт-2 является основным DDL
скрипт и скрипт-7 есть DML
постановка по сценарию-2. Теперь, если исключение происходит в сценарии 5, система откатывает все сценарии до 5, и мы автоматически получаем новое соединение (что нам не нужно, мы хотим выполнить только одну транзакцию). Для сценария-6 это будет работать нормально, но для сценария-7 выдает ошибку, поскольку сценарий 7 зависит от сценария 2, который уже является откатом. Но это неправильно. Скрипт-2 успешно выполнен и откат принудительно при сбое скрипта-5. Таким образом, если у script-5 нет проблем, то script-7 будет успешно выполнен. Теперь мы увидим ошибку в script-7, которая потребляет время разработчика, чтобы исправить это, но ошибки нет вообще, и таких сценариев может быть гораздо больше.
Код C#:
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;
}