【问题标题】:Execution flow of SQL Script in c#c#中SQL脚本的执行流程
【发布时间】:2013-09-25 07:02:34
【问题描述】:

这不是rollback sql transactions if any failed in c#的重复问题。但是这个问题是基于上一个问题的内容。感谢所有对我上一个问题提出意见的人。我尝试了所有这些解决方案,最终发现我在应用程序(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 个脚本以某种方式被执行,而所有其余的脚本都失败了,那么是否有机会自动回滚?

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

任何人都可以用他们宝贵的建议和想法支持我..

任何帮助将不胜感激..

【问题讨论】:

  • 有什么原因你不把这个 SQL 命令序列封装成一个存储过程?
  • @podiluska:要开放,我这里没有尝试存储过程。主要是我不知道如何实现。..
  • @RameezAhmedSayad:tried sqlTransaction..但错误就像在多语句事务中不允许创建命令..在执行第一条语句本身时..
  • 您能否粘贴确切的错误消息,因为理想情况下 CREATE 语句应该是事务性的。
  • @RameezAhmedSayad:多语句事务中不允许创建登录语句

标签: c# sql-server transactions rollback


【解决方案1】:

我已经给出了它可能看起来的骨架。 你可以告诉我你想回滚什么和不回滚什么场景。

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
        }

【讨论】:

  • 那么,为什么我不能在这里给出 drop 语句 else { lvinfo.Items.Add("Create User script execution failed in " + db_select.SelectedItem.ToString() + " database") ; //Drop Statement } 而不是在catch语句中指定..这两者有什么区别?正如我在上面的问题中显示的那样,我有更多这样的脚本。那么,你是想说我应该在所有这些脚本中调用 drop 语句吗?
  • 这个地方 if (!answer.Equals(0)) 可能是一个预期的场景,它只是意味着受影响的行数为零(基于您的更新语句)但是如果您在 sql server 端遇到任何异常,它将抛出一个例外,必须在那里编码。
  • 好的..但是如果它是这样的:在 6 个脚本中,前 3 个成功并在第 4 种方式中失败,我应该能够回滚所有 3..这可能与你所说的?
  • 是的,这是可能的,我可以建议有 2 个字典,一个字典将具有基于序列执行的脚本,而其他则是回滚脚本。然后你可以创建一个通用的 for 方法来回滚。
猜你喜欢
  • 2014-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-10
相关资源
最近更新 更多