28 votes

C # en utilisant une erreur de capture d'instruction

Je suis juste à la recherche à l'instruction d'utilisation, j'ai toujours su ce qu'il fait, mais jusqu'à maintenant pas essayé de l'utiliser, j'en suis venu avec le code ci-dessous:

 using (SqlCommand cmd = 
     new SqlCommand(reportDataSource, 
         new SqlConnection(Settings.Default.qlsdat_extensionsConnectionString)))
 {
     cmd.CommandType = CommandType.StoredProcedure;
     cmd.Parameters.Add("@Year", SqlDbType.Char, 4).Value = year;
     cmd.Parameters.Add("@startDate", SqlDbType.DateTime).Value = start;
     cmd.Parameters.Add("@endDate", SqlDbType.DateTime).Value = end;
     cmd.Connection.Open();

     DataSet dset = new DataSet();
     new SqlDataAdapter(cmd).Fill(dset);
     this.gridDataSource.DataSource = dset.Tables[0];
 }

Cela semble fonctionner, mais il y a tout point dans ce depuis aussi loin que je peux dire que j'aurais encore besoin de joindre ce dans un bloc try catch de catch imprévues par exemple, les erreurs de sql server vers le bas. Ai-je raté quelque chose?

Aussi loin que je peut actuellement le voir juste m'arrête la fermeture et à l'élimination de la cmd mais il n'y aura plus de lignes de code en raison de la try catch encore nécessaires.

56voto

Jason Jackson Points 11563

Lorsque vous faites IO travail, j'ai le code pour attendre une exception.

SqlConnection conn = null;
SqlCommand cmd = null;

try
{
    conn = new SqlConnection(Settings.Default.qlsdat_extensionsConnectionString)
    cmd = new SqlCommand(reportDataSource, conn);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@Year", SqlDbType.Char, 4).Value = year;
    cmd.Parameters.Add("@startDate", SqlDbType.DateTime).Value = start;
    cmd.Parameters.Add("@endDate", SqlDbType.DateTime).Value = end;

        conn.Open(); //opens connection

    DataSet dset = new DataSet();
    new SqlDataAdapter(cmd).Fill(dset);
    this.gridDataSource.DataSource = dset.Tables[0];
}
catch(Exception ex)
{
    Logger.Log(ex);
    throw;
}
finally
{
    if(conn != null)
        conn.Dispose();

        if(cmd != null)
        cmd.Dispose();
}

Edit: Pour être explicite, je éviter l' utilisation de bloc ici parce que je crois qu'il est important pour vous connecter dans des situations de ce genre. L'expérience m'a appris que vous ne savez jamais ce genre de bizarre exception peut pop-up. La journalisation de cette situation pourrait vous aider à détecter un blocage, ou de trouver d'où un changement de schéma affecte un peu utilisée et peu testé partie de vous-même base de code, ou un certain nombre d'autres problèmes.

Edit 2: On peut faire valoir que l'utilisation de bloc peut encapsuler un try/catch dans cette situation, et c'est tout à fait valable, et fonctionnellement équivalent. - Ce vraiment se résume à la préférence. Voulez-vous éviter le supplément de nidification au coût de la manipulation de votre propre disposition? Ou avez-vous engager le supplément de nidification d'avoir l'auto-élimination. J'ai l'impression que l'ancien est plus propre de sorte que je le fais de cette façon. Cependant, je ne réécrit pas le dernier, si je le trouve dans la base de code dans lequel je travaille.

Edit 3: j'ai vraiment, vraiment souhaitez MS avait créé de manière plus explicite la version de l'aide() qui fait qu'il est plus intuitif de ce qui se passe réellement et donné plus de flexibilité dans ce cas. Considérer le suivant, imaginaire de code:

SqlConnection conn = null;
SqlCommand cmd = null;

using(conn = new SqlConnection(Settings.Default.qlsdat_extensionsConnectionString),
          cmd = new SqlCommand(reportDataSource, conn)
{
    conn = new SqlConnection(Settings.Default.qlsdat_extensionsConnectionString);
    cmd = new SqlCommand(reportDataSource, conn);
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@Year", SqlDbType.Char, 4).Value = year;
    cmd.Parameters.Add("@startDate", SqlDbType.DateTime).Value = start;
    cmd.Parameters.Add("@endDate", SqlDbType.DateTime).Value = end;
        cmd.Open();

    DataSet dset = new DataSet();
    new SqlDataAdapter(cmd).Fill(dset);
    this.gridDataSource.DataSource = dset.Tables[0];
}
catch(Exception ex)
{
    Logger.Log(ex);
    throw;
}

À l'aide d'instruction crée un try/finally avec Dispose() appelle dans le enfin. Pourquoi ne pas donner le développeur d'une méthode unifiée de faire de l'élimination et de manipulation d'exception?

18voto

TheSoftwareJedi Points 15921

Ce code doit être le suivant pour garantir la fermeture rapide de la connexion. Fermer uniquement la commande ne ferme pas la connexion:

 using (SqlConnection con = new SqlConnection(Settings.Default.qlsdat_extensionsConnectionString))
using (SqlCommand cmd = new SqlCommand(reportDataSource, con))
         {
             cmd.CommandType = CommandType.StoredProcedure;
             cmd.Parameters.Add("@Year", SqlDbType.Char, 4).Value = year;
             cmd.Parameters.Add("@startDate", SqlDbType.DateTime).Value = start;
             cmd.Parameters.Add("@endDate", SqlDbType.DateTime).Value = end;
             cmd.Connection.Open();

             DataSet dset = new DataSet();
             new SqlDataAdapter(cmd).Fill(dset);
             this.gridDataSource.DataSource = dset.Tables[0];
         }
 

Pour répondre à votre question, vous pouvez faire de même dans un bloc finally, mais cela étend bien le code et garantit que vous vous souvenez de nettoyer.

14voto

Michael Burr Points 181287

Il peut y avoir aucun avantage à utiliser un using énoncé dans ce cas, si vous allez avoir un try/catch/finally bloc de toute façon. Comme vous le savez, l' using déclaration est sucre syntaxique pour un try/finally , qui dispose de l' IDisposable objet. Si vous allez avoir votre propre try/finally de toute façon, vous pouvez certainement faire de l' Dispose vous-même.

- Ce vraiment principalement se résume à un style - votre équipe a peut-être plus à l'aise avec using des déclarations ou using des déclarations peut rendre le code plus propre.

Mais si le passe-partout de l' using déclaration serait le masquage est-il de toute façon, aller de l'avant et de régler les choses vous-même si c'est votre préférence.

6voto

jop Points 31978

Si votre code ressemble à ceci:

 using (SqlCommand cmd = new SqlCommand(...))
{
  try
  {
    /* call stored procedure */
  }
  catch (SqlException ex)
  {
    /* handles the exception. does not rethrow the exception */
  }
}
 

Ensuite, je voudrais le refactoriser pour utiliser try .. catch .. enfin à la place.

 SqlCommand cmd = new SqlCommand(...)
try
{
  /* call stored procedure */
}
catch (SqlException ex)
{
  /* handles the exception and does not ignore it */
}
finally
{
   if (cmd!=null) cmd.Dispose();
}
 

Dans ce scénario, je gérerais l'exception, donc je n'ai pas d'autre choix que d'ajouter cet try..catch, je ferais aussi bien de mettre la clause finally et de me sauver un autre niveau d'imbrication. Notez que je dois faire quelque chose dans le bloc catch et ne pas simplement ignorer l'exception.

4voto

David B Points 53123

utiliser ne consiste pas à intercepter des exceptions. Il s'agit d'éliminer correctement les ressources qui sont hors de la vue du garbage collector.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X