Обработка исключений подключения к базе данных с помощью Linq to SQL и Rx

#linq-to-sql #system.reactive

#linq-to-sql #system.reactive

Вопрос:

Я пытаюсь узнать, как наилучшим образом использовать библиотеку реактивных расширений, и настроил простое тестовое приложение WPF для просмотра таблицы базы данных журнала. В классе ViewModel я заполняю an ObservableCollection первыми 100 записями журнала из Linq to Sql DataContext и пытаюсь использовать Rx, чтобы пользовательский интерфейс оставался отзывчивым.

Следующий фрагмент работает, если база данных недоступна, и в этот момент приложение выдает исключение и выходит из строя. Где было бы лучшее место для обработки исключений подключения к базе данных и почему они не обрабатываются OnError методом наблюдателя?

 ObservableCollection<LogEntry> _logEntries = new ObservableCollection<LogEntry>();

DataContext dataContext = new DataContext( "connection string" );

(from e in dataContext.LogEntries
    select e).Take( 100 ).ToObservable()
    .SubscribeOn( Scheduler.ThreadPool )
    .ObserveOnDispatcher()
    .Subscribe( _logEntries.Add, ex => System.Diagnostics.Debug.WriteLine( ex.ToString() ) );
  

Ответ №1:

Попробуйте это вместо ToObservable:

 public static IObservable<T> SafeToObservable(this IEnumerable<T> This)
{
    return Observable.Create(subj => {
        try {
            foreach(var v in This) {
                subj.OnNext(v);
            }
            subj.OnCompleted();
        } catch (Exception ex) {
            subj.OnError(ex);
        }

        return Disposable.Empty;
    });
}
  

В целом, однако, это не самое лучшее использование Rx, поскольку источник данных не очень легко Rx’идентифицировать — фактически, код выполнит большую часть работы в потоке пользовательского интерфейса, отправит его случайным рабочим потокам, а затем отправит обратно (т. Е. полностью потраченная впустую работа). Задача диспетчер.Здесь вам больше подойдет BeginInvoke.

Комментарии:

1. Спасибо, Пол, что-то подобное должно помочь, я надеялся, что существует какой-то существующий механизм для обработки ошибок во время создания Observable. Приведенный мной пример — это действительно урезанная версия, просто чтобы проиллюстрировать проблему. Фактический поиск данных включает в себя некоторый интервальный опрос и доступ к внешним ресурсам (немного больше Rx’y).

2. В какой момент исключения обычно передаются методу onError?

3. Если при перечислении последовательности произойдет исключение, оно будет передано в onError. Исключение, которое вы видите, сбой подключения к БД, возникает при вызове GetEnumerator. Логически это выходит за рамки последовательности (потому что ее даже нет), и исключение не обрабатывается Rx. Мое предложение состояло бы в том, чтобы обернуть ваш код в try / catch, чтобы разделить концепции, перечисляющие через данные, и попытки получить данные для перечисления.