创建异步方法以使用EF从数据库加载数据

时间:2014-08-05 17:42:38

标签: entity-framework .net-4.0 async-await task-parallel-library

如何使用DbContext和.NET 4.0编写从数据库获取数据的异步方法?

public Task<List<Product>> GetProductsAsync()
{
    // Context.Set<Product>().ToList();
}

所以我们可以等待这个方法的结果

// somewhere
List<Product> products = await repository.GetProductsAsync();

重要的是我不想为这个任务使用线程池线程,因为这是一个IO任务,我需要支持框架4.0,并且EF6仅在4.5中添加了对异步方法的支持,如果我我没弄错。

2 个答案:

答案 0 :(得分:0)

答案 1 :(得分:-1)

安装Entity Framework 6作为Nuget包提供,也适用于.NET 4.在EF6中,async DB调用可以像这个例子一样完成:

 public static async Task<List<Customer>> SelectAllAsync()
  {
            using (var context = new NorthWindEntities())
            {
                var query = from c in context.Customers
                    orderby c.CustomerID ascending
                    select c;
                return await query.ToListAsync();
            }
  } 

这里,DbContext在using块中实例化,查询将在Northwind数据库中搜索其所有客户,并按主键CustomerID进行升序排序。该方法需要使用async关键字进行修饰,并且必须返回所需类型为T的任务,此处为客户列表。然后在这种情况下使用ToListAsync()方法返回结果,并且必须记住使用await关键字。 EF6中还有其他Async方法,例如SaveChangesAsync,SingleOrDefaultAsync等。此外,C#中的异步方法应遵循此指导惯例遵循此命名约定。

要开始在Visual Studio中测试上面的代码,只需创建一个新的控制台应用程序解决方案,在Package Manager控制台中键入:install-package EntityFramework并添加指向本地Northwind数据库的edmx文件。然后,main方法将调用上面的方法,如下所示:

class Program
    {

        static void Main(string[] args)
        {
            Stopwatch sw = Stopwatch.StartNew();
            var task = CustomHelper.SelectAllAsync();
            task.Wait();
            Console.WriteLine("Got data!");
            List<Customer> data = task.Result;
            Console.WriteLine(data.Count);
            Console.WriteLine("Async op took: " + sw.ElapsedMilliseconds);
            sw.Stop();
            sw.Start();
            //data = 
            //var data =  CustomHelper.SelectAll();
            //Console.WriteLine("Got data!");
            //Console.WriteLine(data.Count);
            //Console.WriteLine("Sync operation took: " + sw.ElapsedMilliseconds);
            Console.WriteLine("Press any key to continue ...");
            Console.ReadKey(); 
        }

    }

我发现异步操作比同步操作花费的时间稍长,因此异步数据库调用会有一些时间损失,但允许异步处理,而不是冻结等待结果的调用代码。