0
点赞
收藏
分享

微信扫一扫

Entity Framework Core

干自闭 2022-03-14 阅读 145
linqc#

若要消除可为空引用类型的警告,请从 ContosoUniversity.csproj 项目文件中删除以下行:

<Nullable>enable</Nullable>

ASP.NET Core Web 应用中的异步 EF 方法

异步编程是 ASP.NET Core 和 EF Core 的默认模式。

Web 服务器的可用线程是有限的,而在高负载情况下的可能所有线程都被占用。 当发生这种情况的时候,服务器就无法处理新请求,直到线程被释放。 使用同步代码时,可能会出现多个线程被占用但不能执行操作的情况,因为它们正在等待 I/O 完成。 使用异步代码时,当进程正在等待 I/O 完成,服务器可以将其线程释放用于处理其他请求。 因此,使用异步代码可以更有效地利用服务器资源,并且服务器可以无延迟地处理更多流量。

异步代码会在运行时引入少量开销。 流量较低时,对性能的影响可以忽略不计,但流量较高时,潜在的性能改善非常显著。

在以下代码中,async 关键字和 返回值,await 关键字和 ToListAsync 方法让代码异步执行。

public async Task<Student> OnGetAsync()
{
    Students = await _context.Students.ToListAsync();
    return Students;
}
  • async 关键字让编译器执行以下操作:
    • 为方法主体的各部分生成回调。
    • 创建返回的 Task 对象。
  • 返回类型 Task 表示正在进行的工作。
  • await 关键字让编译器将该方法拆分为两个部分。 第一部分是以异步方式结束已启动的操作。 第二部分是当操作完成时注入调用回调方法的地方。
  • ToListAsync 是 ToList 扩展方法的异步版本。

编写使用 EF Core 的异步代码时需要注意的一些事项:

  • 只有导致查询或发送数据库命令的语句才能以异步方式执行。 这包括 ToListAsyncSingleOrDefaultAsyncFirstOrDefaultAsync 和 SaveChangesAsync。 不包括只会更改 IQueryable 的语句,例如 var students = context.Students.Where(s => s.LastName == "Davolio")
  • EF Core 上下文并非线程安全:请勿尝试并行执行多个操作。
  • 若要利用异步代码的性能优势,请验证在调用向数据库发送查询的 EF Core 方法时,库程序包(如用于分页)是否使用异步。

性能注意事项

创建 PaginatedList 类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity
{
    public class PaginatedList<T> : List<T>
    {
        public int PageIndex { get; private set; }
        public int TotalPages { get; private set; }

        public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
        {
            PageIndex = pageIndex;
            TotalPages = (int)Math.Ceiling(count / (double)pageSize);

            this.AddRange(items);
        }

        public bool HasPreviousPage => PageIndex > 1;

        public bool HasNextPage => PageIndex < TotalPages;

        public static async Task<PaginatedList<T>> CreateAsync(
            IQueryable<T> source, int pageIndex, int pageSize)
        {
            var count = await source.CountAsync();
            var items = await source.Skip(
                (pageIndex - 1) * pageSize)
                .Take(pageSize).ToListAsync();
            return new PaginatedList<T>(items, count, pageIndex, pageSize);
        }
    }
}
举报

相关推荐

0 条评论