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. 查询完成返回结果,并显示到控制台。

posted @ 2016-04-23 19:43  一飞·张  阅读(2665)  评论(0编辑  收藏  举报