Разве плохо использовать вложенные блоки Try..Catch, как это? - PullRequest
2 голосов
/ 21 октября 2009

Это плохая идея? Есть ли лучший способ добиться того же эффекта?

// 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
}

Цель здесь - получить идентификатор записи, если она существует, в противном случае создать эту запись и вернуть ее идентификатор.

Ответы [ 5 ]

6 голосов
/ 21 октября 2009
Main m = dx.Main.SingleOrDefault(s => s.Name == name);

if (m == default(Main))
{
    // it does not exist
}
else
{
    // it does exist
}

Из вопроса не очевидно, является ли тип Main классом или структурой (РЕДАКТИРОВАТЬ: я только что понял, что на самом деле это должен быть класс), поэтому я использовал default() вместо просто по сравнению с null.

6 голосов
/ 21 октября 2009

Вы должны использовать SingleOrDefault, таким образом, если запись не существует, она вернет значение по умолчанию для класса, который является нулевым.

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();
    }

при использовании 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;
}
1 голос
/ 21 октября 2009

Мой вопрос: какой код вы намереваетесь вставить сюда:

// handle this

С первым блоком перехвата вы знаете, что Single () вызвала InvalidOperationException, поскольку последовательность содержит более одного элемента или пуста.

Во втором вы можете получить все виды ошибок. Пустая ссылка, доступ к данным и т. Д. Как вы собираетесь с этим справиться?

Поймай только то, что ты умеешь обрабатывать, и будь как можно более конкретен в типе исключения.

0 голосов
/ 21 октября 2009

В любом случае, я думаю, что вложенные блоки Try Catch хороши, как одноуровневые блоки Catch, каждый из которых обнаруживает свою проблему Хорошо быть конкретным в отношении ошибок. Всеохватывающей должна быть только защитная сетка для производства.

0 голосов
/ 21 октября 2009

Нет, но вы, возможно, захотите перераспределить внутренний блок во внешний метод.

...