Quelle est la meilleure façon d'implémenter la gestion des erreurs pour un Rollback SqlTransaction déjà existant dans une clause catch? Mon code est à peu près comme ceci:Comment intercepter l'exception sur 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;
}
}
}
Je crois que ma demande avait une exception dans le bloc d'essai, ce qui a été pris dans le bloc catch, puis la baisse de prix a été tentée. Cependant, l'erreur que je vois indique quelque chose au sujet d'un SqlTransaction.ZombieCheck(), qui me fait me demander si le RollBack() a jeté une exception aussi bien. Alors, ai-je besoin d'implémenter un type de gestion des erreurs sur le RollBack()? Comment est-ce que je fais cela et réussis à conserver l'exception qui a placé l'exécution dans le bloc catch en premier lieu?
EDIT - Tout mon code:
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;
}
}
}
Je pense que vous l'avez peut-être cloué. J'ai trouvé une autre question sur SO qui traitait de l'utilisation de blocs pour SqlTransaction, et j'ai remarqué que dans leur exemple ils n'utilisent pas non plus le Rollback. Je ne pense pas que ma question soit un double de celui-là. http://stackoverflow.com/questions/1127830/why-use-a-using-statement-with-a-sqltransaction – Jagd
ok la restauration va tenter sans l'explicite, mais conservera-t-elle l'exception interne au lieu de lancer une exception n'a pas la cause la plus probable? – Maslow
@Maslow ce qui est dans l'exception ne sera pas affecté par l'instruction using. Donc, s'il y a une exception interne fournie par SqlCommand.ExecuteScalar, elle sera conservée. –