четверг, 26 декабря 2013 г.

Реализация асинхронной загрузки FillAsync для DbDataAdapter в .NET Framework 4.5 с помощью async и await

Добрый день.
Не так давно я начал изучать нововведения в .NET Framework 4.5
В частности заинтересовала реализация async и await методов.
Сам постоянно работаю с базами данных, которые загружаю с помощью BackgroundWorker или другого потока, чтобы не блокировать интерфейс пользователя при долгой загрузке.
Но меня расстроило отсутствие встроенной возможности асинхронной загрузки через  DbDataAdapter от которого наследуются адаптеры данных. Метод FillAsync просто отсутствует.

OpenAsync() в DbConnection есть, ReadAsync() в DbDataReader есть, а вот FillAsync() в DbDataAdapter нет. Для меня это оказалось серьезным поводом не обновлять мои проекты, т.к. везде используется Fill в адаптере данных.

Но немного подумав, я решил все таки реализовать такой метод сам.
В итоге я написал расширение для DbDataAdapter.
И хочу рассказать вам как я это сделал.

Добавляем в проект новый класс с любым именем, например StaticData.
Со следующим кодом:

using System.Data;
using System.Data.Common;
using System.Threading.Tasks;

namespace AsyncAwaitTesting1
{
    static class StaticData
    {
        public static async Task FillAsync(this DbDataAdapter da, DataTable ds)
        {
            var t = new Task(() => Load(da, ds));            
            t.Start();
            return await t;
        }

        private static int Load(DbDataAdapter da, DataTable dt)
        {            
            return da.Fill(dt);
        }
    }
}




Допустим в проекте уже имеется набор данных. Перейдем к редактору кода:


Добавим код на на рисунке ниже


Прошу обратить внимание что для примера тут расширен адаптер данных только для одной таблицы Codebranch. По идее это нужно сделать для всех таблиц набора данных.
Еще обратите внимание что пространство имен тут тоже другое.

В итоге верхний код добавляет метод FillAsync для адаптера данных.
Работает это так:
int i = await codebranchTableAdapter1.FillAsync(dynPlatformDataSet1.Codebranch);

А вот сам код обработчика


Теперь, при таком сценарии действия метод Fill выполняется асинхронно, не блокируя UI.
Пока неудобство представляет необходимость вручную добавлять методы FillAsync для каждого типизированного адаптера данных.

Хотелось бы чтобы разработчики, все таки учли это и сами включили метод FillAsync для адаптеров данных в будущих редакциях NET Framework.

Пока что все