异步编程
当在数据库中执行查询时,异步操作可避免阻止线程。 对于在客户端应用程序中保持响应式 UI,异步操作很重要,还可以增加 Web 应用程序中的吞吐量,从而释放线程来为 Web 应用程序中的其他请求提供服务。
Micrisift.EntityFrameworkCore
异步方法大部分是定义在Micrisift.EntityFrameworkCore这个命名空间下EntityFrameworkQueryableExtensions等类中的扩展方法,记得using Micrisift.EntityFrameworkCore.
常见的异步方法
AddAsync()、CountAsync()、SaveChanfesAsync()、AllAsunc()等。
TestDbContext ctx = new TestDbContext();
await ctx.SaveChangesAsync();
await ctx.AddAsync(new User { Name ="1" });
await ctx.AddRangeAsync(new[] { new User { Name ="2" } });
await ctx.Users.AnyAsync(u=>u.Id == 5);
为什么有的方法没有异步方法
IQueryable的这些异步的扩展方法都是立即执行的方法,而GroupBy、OrderBy、Join、Where等非立即执行(非终结)的方法则没有对应的异步方法。因为非立即执行的方法并没有实际执行SQL语句,并不是消耗IO的操作。非终结方法不消耗IO.
异步 LINQ 运算符
为了支持以异步方式执行 LINQ 查询,EF Core 提供了一组可执行查询并返回结果的异步扩展方法。 这些与标准同步 LINQ 运算符的对应运算符包括 ToListAsync、 SingleAsync、 AsAsyncEnumerable等:
var blogs = await context.Blogs.Where(b => b.Rating > 3).ToListAsync();
如何异步遍历IQueryable
方式一:ToListAsync()、ToArrayAsync()。注意:结果集合不要太大
在内存中遍历不耗IO
foreach(var a in await ctx.Articles.ToListAsync())
{
Console.WriteLinec(a.Title);
}
方式二:
await foreach(var a in await ctx.Articles.AsAsyncEnumerable())
{
Console.WriteLinec(a.Title);
}
一般情况下数据量没那么大,不会很影响速度,没太大必要这么做。如果遍历照成了性能问题,可以选择这种方式优化。