J'ai rencontré des problèmes concernant une SqlTransaction que j'utilise dans mon code. Au cours de ma recherche sur Google, je vois de nombreuses personnes utiliser une instruction using avec une SqlTransaction.
Quel est l'avantage et/ou la différence de l'utilisation de ce type de déclaration avec une SqlTransaction?
using (SqlConnection cn = new SqlConnection())
{
using (SqlTransaction tr = cn.BeginTransaction())
{
//some code
tr.Commit();
}
}
Actuellement, mon code ressemble à ceci:
SqlConnection cn = new SqlConnection(ConfigurationManager.AppSettings["T3"]);
cn.Open();
SqlTransaction tr = cn.BeginTransaction();
try
{
//some code
tr.Commit();
cn.Close();
}
catch(Exception ex)
{
tr.Rollback();
cn.Close();
throw ex;
}
Quel est l'avantage d'une manière par rapport à l'autre?
Une instruction using
doit être utilisée chaque fois que vous créez une instance d'une classe qui implémente IDisposable
dans le cadre d'un bloc. Il garantit que la méthode Dispose()
sera appelée sur cette instance, qu'une exception soit levée ou non.
En particulier, votre code intercepte uniquement les exceptions gérées, puis détruit le cadre de pile en lançant une nouvelle exception au lieu de renvoyer l'existant.
La bonne façon de procéder est:
using (SqlConnection cn = new SqlConnection(ConfigurationManager.AppSettings["T3"])) {
cn.Open();
using (SqlTransaction tr = cn.BeginTransaction()) {
//some code
tr.Commit();
}
}
Notez que si votre classe a des membres d'instance de types qui implémentent IDisposable
, alors votre classe doit implémenter IDisposable
elle-même et supprimer ces membres lors de son propre appel Dispose()
.
La raison en est que l'objet SqlTransaction sera restauré dans sa méthode Dispose () s'il n'a pas été explicitement validé (par exemple si une exception est levée). En d'autres termes, il a le même effet que votre code, juste un peu plus propre.
Essentiellement, l'utilisation fait la même chose que vous, sauf dans un bloc finally au lieu d'attraper toutes les exceptions:
using (SqlConnection cn = new SqlConnection())
{
using (SqlTransaction tr = cn.BeginTransaction())
{
//some code
tr.Commit();
}
}
est le même que, beaucoup moins de code :)
{
SqlConnection cn = null;
try
{
cn = new SqlConnection();
{
SqlTransaction tr = null;
try
{
tr = cn.BeginTransaction())
//some code
tr.Commit();
}
finally
{
if(tr != null && tr is IDisposable)
{
tr.Dispose();
}
}
}
}
finally
{
if(cn != null && cn is IDisposable)
{
cn.Dispose();
}
}
}
Au final, using
n'est qu'un raccourci pour un motif. Mais c'est un raccourci très tile et utile, car il garantit que vous implémentez le modèle correctement et signifie que vous pouvez le faire avec moins de code.
Dans ce cas, vous n'avez pas correctement implémenté le modèle. Que se passe-t-il dans votre code si l'appel à tr.RollBack()
lève également une exception?
en utilisant l'instruction ferme et supprime votre connexion et transaction pour vous. C'est l'équivalent d'avoir un bloc enfin sur votre try/catch qui fait la disposition.
Vous pouvez également condenser les blocs à l'aide d'un peu comme ceci ...
using (SqlConnection cn = new SqlConnection())
using (SqlTransaction tr = cn.BeginTransaction())
{
//some code
tr.Commit();
}
qui serait à peu près le même que:
SqlConnection cn = null;
SqlTransaction tr = null;
try
{
cn = new SqlConnection());
tr = cn.BeginTransaction());
//some code
tr.Commit();
}
finally
{
if (cn != null)
cn.Dispose();
if (tr != null)
tr.Dispose();
}
Si vous n'utilisez pas de bloc using (), vous devrez appeler explicitement la méthode .Dispose () des objets SqlConnection et SqlTransaction. Si vous ne le faites pas, les ressources non gérées ne seront pas libérées et pourraient provoquer des fuites de mémoire ou d'autres problèmes.
En plus de tout cela, il embellit votre code. Les 7 lignes de code ne sont-elles pas plus belles que les 14 lignes? Je respire un signe de soulagement chaque fois que je vois un bloc d'utilisation. C'est comme ce petit jet de brume qui sort de cette joyeuse odeur. Mmm, je suis un joli bloc de code efficace. Regardez à quel point je gère bien la mémoire et à quel point je suis agréable à l'œil.
En utilisant des garanties, votre objet de connexion sera supprimé après le retour du code. Dispose est utile pour libérer les ressources non gérées. En tant que bonne pratique, si un objet implémente IDisposable, la méthode dispose doit toujours être appelée
L'instruction Using est un raccourci pour gérer correctement une ressource. Vous pouvez trouver plus d'informations sur article MSDN sur l'utilisation de l'instruction