É ruim usar blocos try..catch aninhadas como este?
Pergunta
Esta é uma má idéia? Existe uma maneira melhor de conseguir o mesmo efeito?
// 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
}
O objetivo aqui é obter o ID de um registro se ele existir, caso contrário criar esse registro e devolvê-lo de ID.
Solução
Você deve usar SingleOrDefault, dessa forma, se um registro não existir, ele retornará o valor padrão para a classe que é nulo.
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();
}
é uma boa idéia usar o usando palavra-chave quando se utiliza um 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;
}
Outras dicas
Main m = dx.Main.SingleOrDefault(s => s.Name == name);
if (m == default(Main))
{
// it does not exist
}
else
{
// it does exist
}
Não é evidente a partir da pergunta se o tipo (EDIT: Eu só percebi que, na verdade, deve ser uma classe), daí eu usei Main
é uma classe ou um struct default()
em vez de apenas comparando para null
.
A minha pergunta seria o que o código que você pretende colocar aqui:
// handle this
Com o primeiro bloco de captura, sabe que Individual () jogou um InvalidOperationException porque a sequência contém mais do que um elemento ou está vazio.
No segundo, você pode obter todos os tipos de erros. referência nula, o acesso aos dados, etc. Como você vai lidar com isso?
Apenas pegar o que você sabe como lidar com, e ser tão específico no tipo de exceção que puder.
De qualquer forma, eu acho blocos try catch aninhada são bons, como irmão blocos Catch cada pegar um problema diferente. É bom ser específico sobre os erros. A pega-tudo deve ser apenas uma rede de segurança para a produção.
Não, mas você pode querer refector o bloco interno em um método externo.