Выполнение нескольких запросов базы данных EntityFramework параллельно
Я пытаюсь запустить 3 db запросов параллельно, но я не уверен, что делаю это правильно.
Я сделал 3 функции, каждая из которых делает запрос к db.
private static async Task<string> getAccountCodeAsync(string deviceId)
{
long deviceIdLong = long.Parse(deviceId);
using (var db = new NetworksEntities())
{
return db.Devices.Where(x => x.DeviceId == deviceIdLong).Select(x => x.AccountCode).FirstOrDefault();
}
}
private static async Task<string> getDeviceTypeAsync(string deviceId)
{
long deviceIdLong = long.Parse(deviceId);
using (var db = new NetworksEntities())
{
return db.Devices.Where(x => x.DeviceId == deviceIdLong).Select(x => x.DeviceType).FirstOrDefault().DeviceType;
}
}
private static async Task<string> getUserNameAsync(string userId)
{
int userIdInt;
Int32.TryParse(userId, out userIdInt);
using (var db = new NetworksEntities())
{
return db.Users.Where(x => x.UserId == userIdInt).Select(x => x.Email).FirstOrDefault();
}
}
Затем я в своем коде запускаю три задачи:
var TaskAccountCode = await getAccountCodeAsync(deviceId);
var TaskDeviceType = await getDeviceTypeAsync(deviceId);
var TaskUsername = await getUserNameAsync(userId);
await Task.WhenAll();
//use the results from my 3 tasks to make a new insert into the db.
Является ли то, что я делаю, фактически выполняю свои 3-разрядные запросы параллельно?
EDIT:
private static async Task<string> getAccountCodeAsync(string deviceId)
{
long deviceIdLong = long.Parse(deviceId);
using (var db = new NetworksEntities())
{
return db.Devices.Where(x => x.DeviceId == deviceIdLong).Select(x => x.AccountCode).FirstOrDefaultAsync();
}
}
Ответы
Ответ 1
Вам нужно будет изменить последнюю часть кода, чтобы запустить ее параллельно:
var taskAccountCode = getAccountCodeAsync(deviceId);
var taskDeviceType = getDeviceTypeAsync(deviceId);
var taskUsername = getUserNameAsync(userId);
await Task.WhenAll(taskAccountCode, taskDeviceType, taskUsername);
var accountCode = taskAccountCode.Result;
var deviceType = taskDeviceType.Result;
var username = taskUsername.Result;
Обратите внимание, что существует только один await
. В вашем исходном коде вы await
каждая задача одна за другой заставляете их работать последовательно, а не параллельно.
Кроме того, методы getAccountCodeAsync
и т.д. не являются действительно асинхронными методами (вы должны получить предупреждение компилятора об этом). Тем не менее, Entity Framework 6 поддерживает асинхронные операции и использовать это, вы должны заменить FirstOrDefault
на FirstOrDefaultAsync
. Для каждой параллельной операции вам придется использовать отдельный контекст, и это именно то, что вы делаете.
Ответ 2
Нет, они запускают одно после eachother, если вы вызываете их так, используя метод ожидания foreach, он будет запускать первый метод, затем второй... и т.д. И последняя часть await Task.WhenAll()
, вы не поставили задачи ждать завершения.
Чтобы запустить их параллельно, вы должны сделать это следующим образом:
var TaskAccountCode = getAccountCodeAsync(deviceId);
var TaskDeviceType = getDeviceTypeAsync(deviceId);
var TaskUsername = getUserNameAsync(userId);
await Task.WhenAll(TaskAccountCode, TaskDeviceType,TaskUsername);