回滚sql事务如果c#中有任何失败

时间:2013-09-24 11:57:09

标签: c# sql winforms transactions rollback

我有一个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";

在数据库中执行此操作,如:

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
}

我通过按下按钮一次执行所有这些脚本,所以在我的理解中,我这样做只是一个事务。我想要做的是,如果这些脚本中的任何一个失败,我应该能够完全回滚而不做任何改变。

为了给你一个更好的图片,如果由于某种原因执行了script3失败,它应该自动回滚脚本1和脚本2在数据库中完成的任何事情。

我们怎么做?我用Google搜索并发现了一些不相关的帖子。

任何帮助或想法都会非常感激..

5 个答案:

答案 0 :(得分:2)

使用SqlConnection和SqlTransaction对象。试试这个;

   {       
     // 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();
   }

答案 1 :(得分:1)

根据您的数据库系统,只有DML(数据操作,SELECT / INSERT / UPDATE / DELETE)可以是事务性的,因此可以回滚。 DDL(数据定义,如ALTER或CREATE)不能成为事务的一部分。实际上,根据DBMS,这些语句将在执行时隐含地提交所有先前的DML语句。

如果您需要事务(因为您的DBMS不同或者您实际上有CRUD语句),那么您需要在SqlConnection上调用BeginTransaction并使用生成的对象进行提交或者回滚。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

按照此MSDN reference

中的说明使用SqlTransaction类

答案 4 :(得分:0)

我建议在SQL中处理事务并向用户返回正确的消息。原因是您有两个单独的图层数据访问层(DAL)和UI。

您可以阅读有关DAL HERE

的更多信息

交易具有以下四种标准属性,通常用首字母缩略词ACID表示:

原子性:确保工作单位内的所有操作都成功完成;否则,事务在失败时中止,之前的操作将回滚到以前的状态。

一致性:确保数据库在成功提交的事务时正确更改状态。

隔离:使交易能够独立运作并相互透明。

持久性:确保在系统出现故障时,已提交事务的结果或效果仍然存在。

READ MORE here