文档
C# 进阶篇:EF Core、异步编程与性能优化
背景
Entity Framework Core 是 .NET 最流行的 ORM。掌握其高级用法与异步编程模式,是构建高性能 .NET 应用的基础。
核心概念
1. Task-based 异步模式
// ❌ 同步阻塞
public IActionResult GetBooks()
{
var books = _context.Books.ToList(); // 阻塞线程
return Ok(books);
}
// ✅ 异步非阻塞
public async Task<IActionResult> GetBooksAsync()
{
var books = await _context.Books.ToListAsync(); // 释放线程
return Ok(books);
}
2. EF Core 查询优化
// ❌ N+1 查询 — 每个 Book 的 Author 单独查
var books = await _context.Books.ToListAsync();
foreach (var b in books) Console.WriteLine(b.Author.Name);
// ✅ 预加载 — 一次 JOIN 搞定
var books = await _context.Books
.Include(b => b.Author)
.ToListAsync();
// ✅ 投影 — 只查需要的列
var result = await _context.Books
.Select(b => new { b.Title, AuthorName = b.Author.Name })
.ToListAsync();
3. 并发处理
// 乐观并发 — 用 RowVersion 检测冲突
public class Book
{
// ...
[Timestamp]
public byte[] RowVersion { get; set; }
}
// 乐观并发异常处理
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
// 冲突处理:重试 / 合并 / 通知用户
}
4. 原生 SQL 和存储过程
// 参数化查询防注入
var books = await _context.Books
.FromSqlRaw("SELECT * FROM Books WHERE Price > {0}", minPrice)
.ToListAsync();
// 存储过程
var result = await _context.Database
.ExecuteSqlRawAsync("EXEC UpdateBookPrice @id, @price",
new SqliteParameter("@id", id),
new SqliteParameter("@price", price));
5. CancellationToken
[HttpGet]
public async Task<IActionResult> GetBooks(CancellationToken ct)
{
var books = await _context.Books.ToListAsync(ct);
return Ok(books);
}
// 客户端断开连接时自动取消查询
性能检查清单
| 优化项 | 方法 |
|---|---|
| 查询性能 | 投影(Select)、分页、索引、无跟踪查询 |
| 内存 | AsNoTracking() 只读查询、流式枚举 |
| 并发 | 连接池(AddDbContextPool)、限流中间件 |
| 序列化 | System.Text.Json 源码生成(AOT) |
| 启动 | ReadyToRun、Native AOT 编译 |
思考题
ConfigureAwait(false)在 ASP.NET Core 中还需要吗?为什么?- EF Core 的
IQueryable和IEnumerable有什么区别?为什么要把IQueryable传给 OData? - Native AOT 有什么限制?哪些场景不适合 AOT 编译?