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. 查詢完成返回結果,並顯示到控制台。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM