问题
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:
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.
How can we do this? I googled it and found some irrelevant posts for this.
Any help or ideas would be really appreciated..
回答1:
Use the SqlConnection and SqlTransaction objects. 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();
}
回答2:
Depending on your database system, only DML
(data manipulation, SELECT/INSERT/UPDATE/DELETE) can be transactional and therefor rolled back. DDL
(data definition, like ALTER or CREATE) cannot be part of a transaction. In fact, depending on DBMS
, those statements will implicitely commit all prior DML statements on execution.
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.
回答3:
I use System.Transactions.TransactionScope, if you encase it in a using statement, put your code inside then use scope.complete.
回答4:
Use SqlTransaction Class as explained in this MSDN reference
回答5:
I would recommend taking care of the transaction inside SQL and return proper message to the user. Reason is so you have two separate layers Data Access Layer (DAL) and UI.
You can read more about DAL HERE
Transactions have the following four standard properties, usually referred to by the acronym 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
来源:https://stackoverflow.com/questions/18980972/rollback-sql-transactions-if-any-failed-in-c-sharp