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

时间: 2024-10-05 05:01:59

Entity Framework异步查询和保存的相关文章

Entity Framework的查询

Entity Framework是个好东西,虽然没有Hibernate功能强大,但使用更简便.今天整理一下常见SQL如何用EF来表达,Func形式和Linq形式都会列出来(本人更喜欢Func形式). 1.简单查询: SQL: SELECT * FROM [Clients] WHERE Type=1 AND Deleted=0 ORDER BY ID EF: //Func形式 var clients = ctx.Clients.Where(c => c.Type == 1 && c.D

整理一下Entity Framework的查询

Entity Framework是个好东西,虽然没有Hibernate功能强大,但使用更简便.今天整理一下常见SQL如何用EF来表达,Func形式和Linq形式都会列出来(本人更喜欢Func形式). 1.简单查询: SQL: SELECT * FROM [Clients] WHERE Type=1 AND Deleted=0 ORDER BY ID EF: //Func形式 var clients = ctx.Clients.Where(c => c.Type == 1 && c.D

Entity Framework之查询总结

本节针对EF当前支持的查询方式进行分析比较,和简单自定义条件查询的实现. EF的查询方式 自定义条件查询 一.EF的查询方式 EF提供的查询方式有以下几种 原始SQL查询 LINQ To Entity and Lambda ESQL 与 ObjectQuery ObjectQuery 查询生成器 1.原始SQL查询 在EF 4.1 新增加的DbContext 除了支持LINQ与Lambda查询外,新增了支持原始SQL查询,但是不支持ESQL与ObjectQuery查询. DemoDBEntiti

Entity Framework 多查询 多样写法

使用EF实现多查询,暂未考虑性能问题 2015年10月6日22:26:51 =====正文===== 我在数据库有三个表,如下图: sysMenus与sysFunction有主外键关系,而sysUserInfo则与其他二表并无关联. 我现在使用这三个表针对多种情况使用EF实现多种查询手段 方法一: include方法(或EF自身的导航属性) 查询,要的就是出数据罢了.所以我先说EF自身的导航属性,因为这也算常用方法. 我所说的导航属性就是: 模型表下方显示的,可以看到只有拥有主外键关联的表才会有

探寻ASP.NET MVC鲜为人知的奥秘(2):与Entity Framework配合,让异步贯穿始终

Why 在应用程序,尤其是互联网应用程序中,性能一直是很多大型网站的困扰,由于Web2.0时代的到来,人们更多的把应用程序从C/S结构迁移到B/S结构,这样会带来客户端轻量,部署.试试方便快捷等优势,但是万事万物都有他的两面性,这样的发展趋势同时也带来了其他方便的不好影响,其中很重要的一项就是系统对服务器的性能要求提高,随着用户量增多和系统功能的增加,服务器性能渐渐成了短板. 这种性能的影响,可以从诸多方面进行优化,比如使用负载均衡的服务器,建立服务器集群等方式,但是这是从硬件配置方面的优化,而

动态Entity Framework查询:Dynamic Query 介绍

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 Dynamic Query是一个支持动态Entity Framework查询的库.它的设计初衷是为了减少在管理系统中大量出现的对一个数据集进行查找.排序.分页的这类场景的开发工作量,其设计思想是"markup is code ".通过

Entity Framework 6:专家版本

随着 Entity Framework 最新主版本 EF6 的推出,Microsoft 对象关系映射 (ORM) 工具达到了新的专业高度,与久负盛名的 .NET ORM 工具相比已不再是门外汉. EF 已经完全成熟,正在超越以前广泛使用的工具. Entity Framework 已经度过了青涩期,它最初只是供数据库开发者使用的工具,后来在 .NET 社区的敏捷开发者中间引起轰动. 它学会了如何摆脱应用程序开发模式,转向了普通旧 CLR 对象 (POCO) 模型,支持以测试和域为中心的软件开发,同

Entity Framework 6 暂停重试执行策略

EF6引入一个弹性连接的功能,也就是允许重新尝试执行失败的数据库操作.某些复杂的场景中,可能需要启用或停用重试执行的策略,但是EF框架暂时尚未提供直接的设置开关,将来可能会加入这种配置.幸运的是,很容易自己实现该设置功能. 最简单的注册执行策略的方法是通过基于代码的配置.下面代码是一个典型的配置类,启用SqlAzureExecutionStrategy策略(允许重试执行SQL Azure中已知的可重试异常). 1 using System.Data.Entity; 2 using System.

Entity Framework Code First实体关联数据加载

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 在项目过程中,两个实体数据之间在往往并非完全独立的,而是存在一定的关联关系,如一对一.一对多及多对多等关联.存在关联关系的实体,经常根据一个实体的实例来查询获取与之关联的另外实体的实例. Entity Framework常用处理数据关联加载的方