對catch子句中已存在的SqlTransaction RollBack實現錯誤處理的最佳方式是什麼?我的代碼大致是這樣的:如何在RollBack上捕獲異常
using (SqlConnection objSqlConn = new SqlConnection(connStr)) {
objSqlConn.Open();
using (SqlTransaction objSqlTrans = objSqlConn.BeginTransaction()) {
try {
// code
// more code
// and more code
}
catch (Exception ex) {
// What happens if RollBack() has an exception?
objSqlTrans.Rollback();
throw ex;
}
}
}
我相信我的應用程序必須在try塊,而這又被夾在catch塊,然後回滾試圖在一個例外。但是,我看到的錯誤說了一些關於SqlTransaction.ZombieCheck()的問題,這讓我懷疑RollBack()本身是否也拋出了異常。那麼,我需要在RollBack()中實現某種類型的錯誤處理嗎?我該怎麼做,並設法保留將執行放入catch塊的異常呢?
編輯 - 我的所有代碼:
using (SqlConnection objSqlConn = new SqlConnection(connStr)) {
objSqlConn.Open();
// Begin Transaction
using (SqlTransaction objSqlTrans = objSqlConn.BeginTransaction()) {
try {
// Create file in db (which in turn creates it on disk according to where the
// ...FileStream points)
SqlCommand objSqlCmd = new SqlCommand("usp_FileAdd", objSqlConn, objSqlTrans);
objSqlCmd.CommandType = CommandType.StoredProcedure;
// Sql parameter - report name
SqlParameter objSqlParam1 = new SqlParameter("@ObjectID", SqlDbType.Int);
objSqlParam1.Value = objID;
// Sql out parameter - returns the file path
SqlParameter objSqlParamOutput = new SqlParameter("@filepath", SqlDbType.VarChar, -1);
objSqlParamOutput.Direction = ParameterDirection.Output;
// Add Sql parameters to command obj
objSqlCmd.Parameters.Add(objSqlParam1);
objSqlCmd.Parameters.Add(objSqlParamOutput);
// Execute command object
objSqlCmd.ExecuteNonQuery();
// Path to the FileStream
string path = objSqlCmd.Parameters["@filepath"].Value.ToString();
// Reset command object to get FileStream
objSqlCmd = new SqlCommand(
"SELECT GET_FILESTREAM_TRANSACTION_CONTEXT()",
objSqlConn,
objSqlTrans);
// Execute command object
Object obj = objSqlCmd.ExecuteScalar();
if (obj != DBNull.Value) {
// Byte array representing the FileStream
byte[] fsBytes = (byte[])obj;
SqlFileStream sqlFS = new SqlFileStream(path, fsBytes, FileAccess.Write);
using (FileStream fs = fi.OpenRead()) {
//byte[] b = new byte[1024];
byte[] b = new byte[4096];
int read;
fs.Seek(0, SeekOrigin.Begin);
while ((read = fs.Read(b, 0, b.Length)) > 0) {
sqlFS.Write(b, 0, read);
}
}
sqlFS.Close();
}
// Commit the transaction
objSqlTrans.Commit();
}
catch (Exception ex) {
objSqlTrans.Rollback();
throw ex;
}
}
}
我想你可能已經釘住了它。我在SO上發現了另一個關於使用SqlTransaction塊處理的問題,並且我注意到他們的例子中他們也沒有使用Rollback。我不認爲我的問題是該問題的重複。 http://stackoverflow.com/questions/1127830/why-use-a-using-statement-with-a-sqltransaction – Jagd 2010-04-05 17:18:49
確定回滾將嘗試沒有顯式,但它會保留內部異常,而不是拋出一個異常沒有更可能的原因? – Maslow 2014-10-24 14:57:52
@Maslow使用語句不會影響異常中的內容。所以如果有一個由SqlCommand.ExecuteScalar提供的內部異常,它將被保留。 – 2014-10-24 17:43:19