Выполнение нескольких запросов базы данных 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);