简体   繁体   English

回滚SQL事务(如果在C#中失败)

[英]rollback sql transactions if any failed in c#

I have a windows forms application that executes some sql scripts in a database at the click of a button.These sql scripts do user creation, and giving some permissions like data execute, data read/write etc.. Here is my sample c# code for doing this: 我有一个Windows窗体应用程序,单击按钮即可在数据库中执行一些sql脚本。这些sql脚本可以创建用户,并提供一些权限,例如数据执行,数据读/写等。这是我的示例C#代码这样做:

script1 = "CREATE USER " + username + " FROM LOGIN " + username;
script2 = @"CREATE ROLE [db_execute] AUTHORIZATION [dbo]
                        GRANT EXECUTE TO [db_execute]";

script3 = @"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";

And executing this in the database like: 并在数据库中执行以下操作:

SqlCmd.CommandText = script1;
SqlCmd.Connection = oConnection;
var ans = SqlCmd.ExecuteNonQuery();

if (!ans.Equals(0))
{
    //some task
} else
{
    //messagebox
}

SqlCmd.CommandText = script2;
SqlCmd.Connection = oConnection;
var answer = SqlCmd.ExecuteNonQuery();

if (!answer.Equals(0))
{
    //some task
} else
{
    //messagebox
}

SqlCmd.CommandText = script3;
SqlCmd.Connection = oConnection;
var answ = SqlCmd.ExecuteNonQuery();

if (!answ.Equals(0))
{
    //some task
} else
{
    //messagebox
}

I am executing all these scripts at a time by the press of a button,so in my understanding I am doing this as a single transaction. 我通过按一个按钮一次执行所有这些脚本,所以据我了解,我将其作为单个事务来完成。 What I want to do is that, if in case any of these scripts fail in between I should be able to rollback fully without doing any change. 我想做的是,如果万一这些脚本之间发生故障,我应该能够完全回滚而无需做任何更改。

For giving you a better picture,if in case the execution of script3 got failed for some reason, it should automatically rollback whatever the script1 and script2 done in the database. 为了给您一个更好的画面,如果script3的执行由于某种原因而失败,它应该自动回滚在数据库中执行的script1和script2。

How can we do this? 我们应该怎么做? I googled it and found some irrelevant posts for this. 我在Google上搜索了一下,发现了一些与此无关的帖子。

Any help or ideas would be really appreciated.. 任何帮助或想法将不胜感激。

Use the SqlConnection and SqlTransaction objects. 使用SqlConnection和SqlTransaction对象。 Try this; 尝试这个;

   {       
     // declarations

     try
     {
        // open connection
        trans = conn.BeginTransaction();
        cmd.Transaction = trans;   // Includes this cmd as part of the trans

        SqlCmd.CommandText = script1;
        SqlCmd.Connection = oConnection;
        var ans = SqlCmd.ExecuteNonQuery();


        if (!answ.Equals(0))
        {
           //some task
        } else
        {
           //messagebox
        }

       // Your other queries

       trans.Commit(); // commit transaction

     }
     catch (Exception e){
        trans.Rollback();
        throw e;
     }
     finally{
        conn.Close();
   }

Depending on your database system, only DML (data manipulation, SELECT/INSERT/UPDATE/DELETE) can be transactional and therefor rolled back. 根据您的数据库系统,仅DML (数据操作,SELECT / INSERT / UPDATE / DELETE)可以是事务性的,因此可以回滚。 DDL (data definition, like ALTER or CREATE) cannot be part of a transaction. DDL (数据定义,如ALTER或CREATE)不能成为事务的一部分。 In fact, depending on DBMS , those statements will implicitely commit all prior DML statements on execution. 实际上,根据DBMS ,这些语句将在执行时隐式提交所有先前的DML语句。

If you need transactions (because your DBMS is different or you actually have CRUD statements), then you need to call BeginTransaction on your SqlConnection and use the resulting object to either commit or roll back. 如果您需要事务(因为您的DBMS不同或您实际上有CRUD语句),则需要在SqlConnection上调用BeginTransaction并使用生成的对象进行提交或回滚。

我使用System.Transactions.TransactionScope,如果将其包含在using语句中,则将代码放入其中,然后使用scope.complete。

如本MSDN参考中所述使用SqlTransaction类

I would recommend taking care of the transaction inside SQL and return proper message to the user. 我建议您注意SQL内的事务,并向用户返回正确的消息。 Reason is so you have two separate layers Data Access Layer (DAL) and UI. 原因是您有两个单独的层:数据访问层(DAL)和UI。

You can read more about DAL HERE 您可以在此处详细了解DAL

Transactions have the following four standard properties, usually referred to by the acronym ACID: 事务具有以下四个标准属性,通常以首字母缩写ACID表示:

Atomicity: ensures that all operations within the work unit are completed successfully; 原子性:确保工作单元内的所有操作均成功完成; otherwise, the transaction is aborted at the point of failure, and previous operations are rolled back to their former state. 否则,事务将在失败点中止,并且先前的操作将回滚到它们以前的状态。

Consistency: ensures that the database properly changes states upon a successfully committed transaction. 一致性:确保数据库在成功提交事务后正确更改状态。

Isolation: enables transactions to operate independently of and transparent to each other. 隔离:使事务能够独立运行并且彼此透明。

Durability: ensures that the result or effect of a committed transaction persists in case of a system failure. 耐用性:确保在系统故障的情况下持久化已提交事务的结果或效果。

READ MORE here 在这里阅读更多

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM