Как я могу поймать и элегантно обработать исключение, когда база данных недоступна в WPF

Я пытаюсь поймать исключение, когда база данных недоступна в WPF с EF. Я использую MVVM и шаблон Repo с IUnityContainer в C#.

Моя проблема заключается в том, что, если база данных недоступна, программа аварийно завершает работу оператора InitializeComponent() в коде за представлением. Я попытался выполнить поиск по выявлению исключений и обработке ошибок и т. Д., И большинство предложений сосредоточены вокруг логики Try Catch, что и следовало ожидать. Я попытался обернуть оператор в блок try-catch, как показано ниже, но он все равно вылетает в том же месте на InitalizeComponent.

Public MyListView() {
    try {
        IntializeComponent();
    } catch (Exception) {
        throw;
    }    
}

Я также пытался добавить блоки Try-Catch в различные другие точки моего кода, например, где инициализирована БД:

Database.SetInitializer(new DataInitialiser());

Где зарегистрирован контейнер Unity:

_container.RegisterType<IRepo<MyList>, MyListRepo>(new TransientLifetimeManager());

и куда загружаются данные:

MyLists = new ObservableCollection<MyList>(await _repo.GetAllAsync());

Я хотел бы сохранить шаблон MVVM, поэтому перехватывайте исключение и предоставляйте элегантный ответ пользователю из ViewModel. Поэтому мой конкретный вопрос: где я могу поймать исключение, когда база данных недоступна?

Заранее спасибо.

2 ответа

Решение

Типично using вокруг каждого DbContext будет защищен try / catch блок.

Если вы хотите что-то более централизованное, вы можете сделать что-то вроде этого:

public static class EfHelper
{
    public static void SafeExecute<T>(Action<T> action) where T : DbContext, new()
    {
        try
        {
            using (var context = new T())
            {
                action.Invoke(context);
            }
        }
        catch (Exception ex)
        {
            // Put your standard error handling here.
            Debug.WriteLine("There was an error");
        }
    }
}

Использование:

void Main()
{
    EfHelper.SafeExecute<TestContext>(context =>
    {
        context.DoSomething();
    });
}

Возможно, вы захотите немного расширить это, чтобы позволить вызывающей стороне узнать, была ли операция успешной или неудачной. Вы можете сделать это, вернув boolили распространение исключения, если установлен другой флаг и т. д.

Если у вас установлен LINQPad, вы можете увидеть простую демонстрацию здесь: http://share.linqpad.net/4x2g36.linq

Основной причиной моей проблемы было то, что я нарушил принцип инкапсуляции. Я думал, что я был бы умным и поместил бы таблицу, на которую часто ссылаются в списке, в статический класс, на который ссылается представление. Вот почему исключение было выброшено "за пределы" ViewModel - я знаю ошибку новичка. После того, как я установил, что использование вокруг DbContext работало отлично.

Спасибо за все советы

Другие вопросы по тегам