C# c语言中SQL脚本的执行流程#

C# c语言中SQL脚本的执行流程#,c#,sql-server,transactions,rollback,C#,Sql Server,Transactions,Rollback,这不是一个重复的问题。但这个问题是基于上一个问题的内容。感谢所有对我的最后一个问题发表意见的人。我尝试了所有这些解决方案,最终发现我在应用程序(DDL)中使用的脚本在多语句事务中是不允许的 我的整个代码如下所示: script1 = "CREATE USER " + username + " FROM LOGIN " + username; script2 = "CREATE ROLE " + rolename; script3 = @"CREATE ROLE [db_execute] AU

这不是一个重复的问题。但这个问题是基于上一个问题的内容。感谢所有对我的最后一个问题发表意见的人。我尝试了所有这些解决方案,最终发现我在应用程序(DDL)中使用的脚本在多语句事务中是不允许的

我的整个代码如下所示:

script1 = "CREATE USER " + username + " FROM LOGIN " + username;

script2 = "CREATE ROLE " + rolename;

script3 = @"CREATE ROLE [db_execute] AUTHORIZATION [dbo]
                        GRANT EXECUTE TO [db_execute]";

script4 = @"DECLARE @rolename varchar(max)
                    SET @rolename ='{0}'
                    EXEC sp_addrolemember N'db_execute',@rolename
                    EXEC sp_addrolemember N'db_datareader', @rolename
                    EXEC sp_addrolemember N'db_datawriter', @rolename";
script_result = string.Format(script4, rolename);

script6 = "EXEC sp_addrolemember '{0}', '{1}'";
            outp = string.Format(script6, rolename, username);

script7 = @"select m.name as Member, r.name as Role
                    from sys.database_role_members
                    inner join sys.database_principals m on sys.database_role_members.member_principal_id = m.principal_id
                    inner join sys.database_principals r on sys.database_role_members.role_principal_id = r.principal_id";
并以如下所示的相同方式执行所有这些操作:

SqlCommand SqlCmd = new SqlCommand();

//Create User Script Execution
SqlCmd.CommandText = script1;
SqlCmd.Connection = oConnection;        
lvinfo.Items.Add("Executing Create User script in " + dbname + " database");
var answer = SqlCmd.ExecuteNonQuery();

//Checking whether execution completed successfully
if (!answer.Equals(0))
{
lvinfo.Items.Add("Create User script executed successfully in " + dbname + " database");                                                                          
}
else
{
lvinfo.Items.Add("Create User script execution failed in " + db_select.SelectedItem.ToString() + " database");
}
尽管我只写了这段代码,但现在我对这些脚本的执行有一些疑问。上面显示的所有脚本一次执行一个按钮。我想知道的是,这些脚本是否会一次完全执行?意味着,在执行这些脚本时,是否有可能一次执行失败?可能是数据库断开连接,或者是任何其他错误

让我向您展示一个我要问的示例:如果前3个脚本以某种方式被执行,而其余所有脚本都失败了,那么是否有机会自动回滚

或者,在执行整个代码之前,我的代码是否会检查是否存在任何错误或失败的机会,以便它永远不需要回滚

有谁能支持我提出宝贵的建议和想法吗


任何帮助都将不胜感激。

我已经为它的外观提供了一个框架。 你可以告诉我你想回滚什么和什么不想回滚的场景

var scriptToExecute = new Dictionary<int, string>();
            var scriptToRollback = new Dictionary<int, string>();

        try
        {
            using (SqlCommand SqlCmd = new SqlCommand())
            {
                //Create User Script Execution
                SqlCmd.CommandText = script1;
                SqlCmd.Connection = oConnection;
                lvinfo.Items.Add("Executing Create User script in " + dbname + " database");
                var answer = SqlCmd.ExecuteNonQuery();

                //Checking whether execution completed successfully
                if (!answer.Equals(0))
                {
                    lvinfo.Items.Add("Create User script executed successfully in " + dbname + " database");
                }
                else
                {
                    lvinfo.Items.Add("Create User script execution failed in " + db_select.SelectedItem.ToString() + " database");
                }
            }
        }
        catch (SqlException)
        {
            string rollbackScript = string.Empty;
            for (int i = scriptExecuting; i > 0; i--)
            {
                scriptToRollback.TryGetValue(i, rollbackScript);
                if (!string.IsEmpty(rollbackScript))
                {
                    //Execute the scripts here.
                }
            }
        }



        finally
        {
            //If connection is open then close the active connection
        }
var scriptToExecute=new Dictionary();
var scriptToRollback=新字典();
尝试
{
使用(SqlCommand SqlCmd=new SqlCommand())
{
//创建用户脚本执行
SqlCmd.CommandText=script1;
SqlCmd.Connection=occonnection;
添加(“在“+dbname+”数据库中执行创建用户脚本”);
var answer=SqlCmd.ExecuteNonQuery();
//正在检查执行是否成功完成
如果(!answer.Equals(0))
{
lvinfo.Items.Add(“创建在“+dbname+”数据库中成功执行的用户脚本”);
}
其他的
{
lvinfo.Items.Add(“在“+db_select.SelectedItem.ToString()+”数据库中创建用户脚本执行失败”);
}
}
}
捕获(SqlException)
{
string rollbackScript=string.Empty;
对于(int i=scriptExecuting;i>0;i--)
{
TryGetValue(i,rollbackScript);
如果(!string.IsEmpty(rollbackScript))
{
//在这里执行脚本。
}
}
}
最后
{
//如果连接打开,则关闭活动连接
}

您为什么不将这一系列SQL命令封装为存储过程?@podiluska:To open,我没有在这里尝试存储过程。主要是因为我不知道如何实现这一点。@RameezAhmedSayad:trued sqlTransaction..但错误类似于在多语句事务中不允许使用create命令..在执行第一个语句本身时..能否粘贴准确的错误消息,因为理想情况下create语句应该是事务性。@RameezAhmedSayad:CREATE LOGIN语句不允许在多语句事务中使用。因此,为什么我不能在这里给drop语句{lvinfo.Items.Add(“CREATE User script execution failed in”+db_select.SelectedItem.ToString()+“database”);//drop语句}而不是在catch语句中指定它..这两者之间有什么区别?正如我在上面的问题中所展示的那样,我有更多这样的脚本。那么,你是想说我应该在所有这些脚本中调用drop语句吗?如果(!answer.Equals(0))可能是一个预期的场景,这仅仅意味着没有受影响的行是零(基于你的update语句)但是,如果在sql server端遇到任何异常,它将抛出一个异常,并且必须在那里进行编码。好的..但是如果是这样的情况:在6个脚本中,前3个成功,第4个失败意味着,我应该能够回滚所有3个..你所说的有可能吗?是的,有可能,我建议有2个字典,一个字典将有基于序列执行的脚本和另一个字典的回滚脚本。然后,您可以为回滚创建泛型for方法。