È male usare blocchi nidificati Try..Catch come questo?
Domanda
È una cattiva idea? C'è un modo migliore per ottenere lo stesso effetto?
// assume that "name" is a string passed as a parameter to this code block
try
{
MainsDataContext dx = new MainsDataContext();
try
{
Main m = dx.Main.Single(s => s.Name == name);
return m.ID;
}
catch (InvalidOperationException)
{
Guid g = Guid.NewGuid();
Main s = new Main
{
Name = name,
ID = g
};
dx.Mains.InsertOnSubmit(s);
dx.SubmitChanges();
return g;
}
}
catch (Exception ex)
{
// handle this
}
L'obiettivo qui è quello di ottenere l'ID di un record se esiste, altrimenti creare quel record e restituire il suo ID.
Soluzione
Dovresti usare SingleOrDefault, in questo modo se un record non esiste restituirà il valore predefinito per la classe che è null.
MainsDataContext dx = null;
try
{
dx = new MainsDataContext();
Main m = dx.Main.SingleOrDefault(s => s.Name == name);
if ( m == null)
{
Guid g = Guid.NewGuid();
m = new Main
{
Name = name,
ID = g
};
dx.Mains.InsertOnSubmit(m);
dx.SubmitChanges();
}
return m.ID;
}
catch (Exception ex)
{
// handle this
}
finally
{
if(dx != null)
dx.Dispose();
}
è una buona idea usare la parola chiave usando quando si utilizza un DataContext
using ( MainsDataContext dx = new MainsDataContext())
{
Main m = dx.Main.SingleOrDefault(s => s.Name == name);
if ( m == null)
{
Guid g = Guid.NewGuid();
m = new Main
{
Name = name,
ID = g
};
dx.Mains.InsertOnSubmit(m);
dx.SubmitChanges();
}
return m.ID;
}
Altri suggerimenti
Main m = dx.Main.SingleOrDefault(s => s.Name == name);
if (m == default(Main))
{
// it does not exist
}
else
{
// it does exist
}
Non è chiaro dalla domanda se il tipo (EDIT: ho appena capito che in realtà deve essere una classe), quindi Ho usato Main
sia una classe o una struttura default ()
invece di confrontarmi con null
.
La mia domanda sarebbe quale codice intendi inserire qui:
// handle this
Con il primo blocco catch, sai che Single () ha generato un InvalidOperationException perché la sequenza contiene più di un elemento o è vuota.
Nel secondo, potresti ottenere tutti i tipi di errori. Riferimento null, accesso ai dati, ecc. Come gestirli?
Prendi solo ciò che sai come gestire ed essere il più specifico possibile nel tipo di eccezione.
Comunque, penso che i blocchi Try Catch nidificati siano buoni, come i blocchi Catch di pari livello che rilevano ciascuno un problema diverso. È bene essere specifici sugli errori. Tutto sommato dovrebbe essere solo una rete di sicurezza per la produzione.
No, ma potresti voler ricodificare il blocco interno in un metodo esterno.