Concordo pienamente.
Supponiamo di dover eseguire una stored procedure per la lettura dei dati (ad es. "spGetItem"). Il code snippet per effettuare questa operazione è il seguente:

SqlConnection cn = null;
SqlCommand cmd = null;
SqlDataReader dr = null;

try
{
  cn.Open();
  cmd = new SqlCommand("spGetItem", cn);
  cmd.CommandType = CommandType.StoredProcedure;
  cmd.Parameters.AddWithValue("@Id", id);
  dr = cmd.ExecuteReader();
  while (dr.Read())
  {
    // do something with DataReader
  }  
}
finally
{
  if (dr != null)
  {
    dr.Close();
    dr.Dispose();
  }
  if (cmd != null)
    cmd.Dispose();
  if (cn != null)
  {
    cn.Close();
    cn.Dispose();
  }
}


In questo modo tutti gli oggetti in uso (connection, command e datareader) vengono chiusi e "disposati" in modo corretto nello statement finally.
Questo codice però è piuttosto gravoso da scrivere e mantenere (senza contare che anche le singole distruzioni degli oggetti dovrebbero stare dentro un blocco try...catch) e potrebbe facilmente indurre ad errori.

Usando il fantastico statement "using" il codice di cui sopra si riduce a:

using (SqlConnection cn = new SqlConnection(ConnectionString))
{
  cn.Open();
  using (SqlCommand cmd = new SqlCommand("spGetItem", cn))
  {
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("@Id", id);
    using (SqlDataReader dr = cmd.ExecuteReader())
    {
      while (dr.Read())
      {
        // do something with DataReader
      }
    }
  }
}


Decisamente più compatto, meno oneroso da scrivere e anche più sicuro.

Spero di aver convinto anche i più scettici

HTH

Matteo Casati
GURU4.net
575 messaggi dal 23 giugno 2003
www.padovaboy.it
"Defines a scope, outside of which an object or objects will be disposed."

Opporca! Non lo sapevo mica :P

Grazie per la scoperta...ma se volessi comunque mettere un bel try catch dentro all'using?

Riprendendo l'esempio del "mitico" verrebbe una cosa del genere:?
Come si impatta questa struttura sul try catch?

Grazie a tutti!


using (SqlConnection cn = new SqlConnection(ConnectionString))
 {
   try {
      cn.Open();
        using (SqlCommand cmd = new SqlCommand("spGetItem", cn))
          {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.AddWithValue("@Id", id);
            using (SqlDataReader dr = cmd.ExecuteReader())
             {
                while (dr.Read())
                  {
                     // do something with DataReader
                  }
             }
          }
   } Catch (Exception ex){
     // log....
   }
} 

www.padovaboy.it dal 2001 con furore :D
buahahhaah, questo tuo esempio mi ricorda un sacco di cose!!!

imperugo
Microsoft MVP
myblog : http://www.tostring.it
padovaboy ha scritto:
Riprendendo l'esempio del "mitico"

 Chi è il "mitico"?

Come si impatta questa struttura sul try catch?

In compilazione lo statement using viene sostituito da un blocco "try...finally..."

Ad esempio:

using (StreamReader reader = new StreamReader(@"C:\My Files\test.txt"))
{
     string text = reader.ReadToEnd();
}


Equivale *esattamente* a:

StreamReader reader = new StreamReader(@"C:\My Files\test.txt");
try
{
    string text = reader.ReadToEnd();
}
finally
{
    reader.Dispose();
}


Infatti il codice MSIL del codice che usa lo statement "using" è:
// Code size       31 (0x1f)
  .maxstack  2
  .locals init ([0] class [mscorlib]System.IO.StreamReader reader,[1] string text)
  IL_0000:  ldstr      "C:\\My Files\\test.txt"
  IL_0005:  newobj     instance void [mscorlib]System.IO.StreamReader::.ctor(string)
  IL_000a:  stloc.0
  .try
  {
    IL_000b:  ldloc.0
    IL_000c:  callvirt   instance string [mscorlib]System.IO.TextReader::ReadToEnd()
    IL_0011:  stloc.1
    IL_0012:  leave.s    IL_001e
  }  // end .try
  finally
  {
    IL_0014:  ldloc.0
    IL_0015:  brfalse.s  IL_001d
    IL_0017:  ldloc.0
    IL_0018:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_001d:  endfinally
  }  // end handler
  IL_001e:  ret


(source: Why use using?)

Detto questo nulla ti vieta di racchiudere tutto il corpo del metodo (o una sua parte) in un blocco try...catch esterno, ad esempio, come nel tuo esempio, per gestire il log delle eccezioni.

Il vantaggio è che non sei costretto a gestire eventuali eccezioni per ogni oggetto al fine di assicurarne la distruzione (rischiando di dimenticartene qualcuno!) ma solo le eccezioni significative per il tuo metodo. Un bel risparmio, no?

Matteo Casati
GURU4.net
imperugo ha scritto:
buahahhaah, questo tuo esempio mi ricorda un sacco di cose!!!


Tipo?

Matteo Casati
GURU4.net
Tipo?
Segretissimo (chiedi a d , cmq sappi effettuare il dispose dei reader è un optional!!!
buahahah

imperugo
Microsoft MVP
myblog : http://www.tostring.it
imperugo ha scritto:
effettuare il dispose dei reader è un optional!!!
buahahah


Già, non è detto che una voglia un'applicazione funzionante, per cui puoi anche evitarti le dispose...

Matteo Casati
GURU4.net

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.