并行运行几个EntityFramework数据库查询

时间:2014-04-08 06:13:52

标签: c# asp.net multithreading asynchronous task-parallel-library

我正在尝试并行运行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 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).FirstOrDefaultAsync();
        }
    }

2 个答案:

答案 0 :(得分:17)

您必须更改代码的最后部分才能使其并行运行:

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等并不是真正的异步方法(您应该收到编译器警告)。但是,实体框架6支持异步操作并使用它,您应该将FirstOrDefault替换为FirstOrDefaultAsync。对于每个并行操作,您将必须使用单独的上下文,这正是您正在做的事情。

答案 1 :(得分:2)

如果你使用等待foreach方法调用它们,它们会在彼此之后运行一个,它将运行第一个方法,然后运行第二个方法......等等。最后一部分await Task.WhenAll(),你没有提供等待完成的任务。

要并行运行它们,你必须这样做:

var TaskAccountCode = getAccountCodeAsync(deviceId);
var TaskDeviceType = getDeviceTypeAsync(deviceId);
var TaskUsername = getUserNameAsync(userId);
await Task.WhenAll(TaskAccountCode, TaskDeviceType,TaskUsername);