Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running several EntityFramework database queries in parallel

I am trying to run 3 database queries in parallel but I'm not sure that I am doing it correctly.

I have made 3 functions which each make a query to the database.

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();
    }
}   

I then in my code I run the three tasks:

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.

Is what I am doing actually running my 3 db queries in parallel?

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();
    }
}
like image 450
Zapnologica Avatar asked Apr 08 '14 06:04

Zapnologica


2 Answers

You will have to change the last part of the code to make it run in parallel:

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;

Notice that there is only one await. In your original code you await every task one after the other making them run in sequence instead of in parallel.

Also, the methods getAccountCodeAsync etc. are not really async methods (you should get a compiler warning about this). However, Entity Framework 6 has support for async operations and to use that you should replace FirstOrDefault with FirstOrDefaultAsync. For each parallel operation you will have to use a separate context, and that is exactly what you are doing.

like image 55
Martin Liversage Avatar answered Sep 29 '22 17:09

Martin Liversage


No they run one after eachother if you call them like that using await foreach method, it will run first method, then the second one...etc. And the last part await Task.WhenAll(), you did not supplied the tasks to wait for completion.

To run them in parallel you have to do it like this:

var TaskAccountCode = getAccountCodeAsync(deviceId);
var TaskDeviceType = getDeviceTypeAsync(deviceId);
var TaskUsername = getUserNameAsync(userId);
await Task.WhenAll(TaskAccountCode, TaskDeviceType,TaskUsername);   
like image 29
Mihai Hantea Avatar answered Sep 29 '22 18:09

Mihai Hantea