У меня имеется WPF-приложение, работающее с базой данных. Количество записей в базе довольно большое и постоянно растёт. В проекте используется ORM(EF 6).
Имеется некий класс, работающий непосредственно с контекстом базы данных:
public class Store : IStore {...}
В интерфейсе класса определён ряд методов, код в которых обращается непосредственно к базе через EF-контекст, соответственно, выполнение метода занимает довольно длительное время, что может вызвать простой интерфейса пользователя, если я всё правильно понимаю. Следовательно, нужно вынести операции получения данных из базы в отдельные потоки. Так, скажем, в Store определен метод:
public ICollection
Если я правильно понимаю, мне необходимо добавить его асинхронную реализацию:
public async Task
Как правильно воспользоваться таким методом в самом приложении в ViewModel, Скажем, чтобы, пока данные загружаются, в StatusBar отображался прогресс загрузки данных, а DataGrid отобразил результат как только данные загрузятся?
Ответ
Окей, давайте начнём с Task.Factory.StartNew. Это нужно только если ваш запрос к базе данных не поддерживает асинхронность сам, и требует выделения отдельного потока (кстати, лучше писать просто Task.Run).
Для свежего Entity Framework это не так, асинхронные функции поддерживаются правильно, из коробки: Entity Framework tutorial: async query and save
С асинхронностью на уровне базы данных вам не нужно создавать отдельные потоки.
По поводу прогресса, с этим хуже. EF не поддерживает информацию о прогрессе операции, так что вы можете просто вывести состояние «читаю», и считывать до тех пор, пока не закончите.
В случае, когда/если будет имплементирована поддержка прогресса, вам можно будет воспользоваться интерфейсом IProgress
Таким образом, код в VM будет выглядеть так:
IsLoading = true;
var localData = await model.LoadDataAsync();
IsLoading = false;
Data = localData;
Скорее всего, вы не захотите выкладывать модельные классы для View, поэтому вам понадобится обёртка, создающая VM-объекты для ваших entity:
// в модели
IQueryable
// в VM
IsLoading = true;
var localData = new List
Ну и, как верно отмечает @Pavel Mayorov, возможно вы захотите ловить исключения, так что вам понадобится try:
IsLoading = true;
var localData = new List
Или, если вы хотите, чтобы данные появлялись не все вместе, а по мере подгрузки, наверное подойдёт просто
await model.GetData().ForEachAsync(entity => Data.Add(new EntityVM(entity));
(но здесь я не уверен, т. к. ни разу не пробовал).
Комментариев нет:
Отправить комментарий