你的位置:首页 > ASP.net教程

[ASP.net教程]Entity Framework异步查询和保存


EF6开始提供了通过async和await关键字实现异步查询和保存的支持(.net 4.5及更高版本)。虽然不是所有的操作都能从异步中获益,但是耗时的操作、网络或IO密集型任务中,使用异步可以提升客户端性能和增强服务器的扩展性。

本文将覆盖一下主题:

  • 实例演练异步操作
  • 创建模型
  • 创建同步程序
  • 改为异步操作

实例演练异步操作

下面演练将通过对比,很容易的观察异步操作和同步操作,该演练目的不是说明何时才是异步操作的关键场景。

创建模型

下面使用CodeFirst的流程创建模型并生成数据库,不过异步方法可以很好的工作于所有EF模型,包括EF设计器生成的模型。

创建一个控制台应用程序AsyncDemo。

添加EntityFramework NuGet包到项目中。

添加Model.cs到项目中,代码如下:

 1 using System.Collections.Generic;  2 using System.Data.Entity;  3  4 namespace AsyncDemo  5 {  6   public class BloggingContext : DbContext  7   {  8     public DbSet<Blog> Blogs { get; set; }  9     public DbSet<Post> Posts { get; set; } 10   } 11 12   public class Blog 13   { 14     public int BlogId { get; set; } 15     public string Name { get; set; } 16 17     public virtual List<Post> Posts { get; set; } 18   } 19 20   public class Post 21   { 22     public int PostId { get; set; } 23     public string Title { get; set; } 24     public string Content { get; set; } 25 26     public int BlogId { get; set; } 27     public virtual Blog Blog { get; set; } 28   } 29 }

 

创建同步程序

有了EF模型,下面通过代码模拟数据库存取。

 1 using System;  2 using System.Linq;  3  4 namespace AsyncDemo  5 {  6   class Program  7   {  8     static void Main(string[] args)  9     { 10       PerformDatabaseOperations(); 11 12       Console.WriteLine(); 13       Console.WriteLine("Quote of the day"); 14       Console.WriteLine(" Don't worry about the world coming to an end today... "); 15       Console.WriteLine(" It's already tomorrow in Australia."); 16 17       Console.WriteLine(); 18       Console.WriteLine("Press any key to exit..."); 19       Console.ReadKey(); 20     } 21 22     public static void PerformDatabaseOperations() 23     { 24       using (var db = new BloggingContext()) 25       { 26         // Create a new blog and save it 27         db.Blogs.Add(new Blog 28         { 29           Name = "Test Blog #" + (db.Blogs.Count() + 1) 30         }); 31         db.SaveChanges(); 32 33         // Query for all blogs ordered by name 34         var blogs = (from b in db.Blogs 35               orderby b.Name 36               select b).ToList(); 37 38         // Write all blogs out to Console 39         Console.WriteLine(); 40         Console.WriteLine("All blogs:"); 41         foreach (var blog in blogs) 42         { 43           Console.WriteLine(" " + blog.Name); 44         } 45       } 46     } 47   } 48 }

上面代码通过调用PerformDatabaseOperations() 保存一个Blog对象到数据库中,然后从数据库中检索所有Blog,并显示到控制台,然后显示一行文本”Quote of the day“。

由于上面程序是同步执行的,所有可以观察到程序按下面流程执行:

  1. SaveChanges保存Blog对象到数据库中。
  2. SaveChanges完成。
  3. 发送查询Blog请求到数据库。
  4. 查询返回结果,并写入控制台。
  5. 显示文本“Quote of the day”到控制台。

 

改造为异步操作

对上面程序加以修改,使用async和await关键字实现异步操作。

 1 using System;  2 using System.Data.Entity;  3 using System.Linq;  4 using System.Threading.Tasks;  5  6 namespace AsyncDemo  7 {  8   class Program  9   { 10     static void Main(string[] args) 11     { 12       var task = PerformDatabaseOperations(); 13 14       Console.WriteLine("Quote of the day"); 15       Console.WriteLine(" Don't worry about the world coming to an end today... "); 16       Console.WriteLine(" It's already tomorrow in Australia."); 17 18       task.Wait(); 19 20       Console.WriteLine(); 21       Console.WriteLine("Press any key to exit..."); 22       Console.ReadKey(); 23     } 24 25     public static async Task PerformDatabaseOperations() 26     { 27       using (var db = new BloggingContext()) 28       { 29         // Create a new blog and save it 30         db.Blogs.Add(new Blog 31         { 32           Name = "Test Blog #" + (db.Blogs.Count() + 1) 33         }); 34         Console.WriteLine("Calling SaveChanges."); 35         await db.SaveChangesAsync(); 36         Console.WriteLine("SaveChanges completed."); 37 38         // Query for all blogs ordered by name 39         Console.WriteLine("Executing query."); 40         var blogs = await (from b in db.Blogs 41               orderby b.Name 42               select b).ToListAsync(); 43 44         // Write all blogs out to Console 45         Console.WriteLine("Query completed with following results:"); 46         foreach (var blog in blogs) 47         { 48           Console.WriteLine(" - " + blog.Name); 49         } 50       } 51     } 52   } 53 }

现在程序变为异步执行,可以观察到异步执行顺序为:

  1. 发送SaveChanges请求到数据库。
  2. 该请求发送给数据库时,当前线程不在占用CPU时间,从方法PerformDatabaseOperations中返回(虽然该方法还没有执行完成),控制权返回给主线程执行。
  3. 显示字符串“Quote of the day ”到控制台。
  4. SaveChanges完成。
  5. 发起查询Blogs请求到数据库。
  6. 查询完成返回结果,并显示到控制台。