EF Core 迁移与查询优化实战
EF Core 提升了数据访问效率,但模型变更和 LINQ 查询最终仍会转化为数据库操作。团队需要审查生成的迁移与 SQL,并用数据库指标验证性能,而不能只看到代码可以运行。
核心原则
- 每次模型变更生成独立迁移,检查 Up、Down 以及默认值和数据转换。
- 生产发布使用经过审查的迁移脚本,避免应用启动时多实例同时迁移。
- 只读查询使用 AsNoTracking,并投影成 DTO,减少跟踪和无用列。
- 警惕循环内访问导航属性产生 N+1,按场景选择投影、Include 或拆分查询。
- 分页优先使用稳定排序和游标方式,大偏移量场景避免深度 Skip。
推荐的实践步骤
优化前打开 EF Core 命令日志并定位慢 SQL,再查看执行计划和索引。列表页面通常直接 Select 到 DTO,仅加载所需字段;更新时按主键读取跟踪实体并保存。大表加非空列或建索引需要评估锁影响,可以拆成可回滚的多阶段迁移。
var page = await db.Orders
.AsNoTracking()
.Where(x => x.CustomerId == customerId)
.OrderByDescending(x => x.CreatedAt)
.Select(x => new OrderRow(x.Id, x.Total, x.Status))
.Take(50)
.ToListAsync(cancellationToken);
示例用于说明实现思路,实际项目还应结合所使用的框架版本、部署环境和业务约束进行调整。重要配置要进入版本管理,并在测试环境验证后再发布。
常见误区
- 直接执行未审查的自动迁移,可能在高峰期锁住大表。
- 为所有查询添加 Include 会产生巨大结果集和重复数据。
- 读取页面仍启用实体跟踪,会增加内存与变更检测成本。
上线前检查清单
- 确认“每次模型变更生成独立迁移,检查 Up、Down 以及默认值和数据转换”已经通过代码审查或运行验证。
- 确认“生产发布使用经过审查的迁移脚本,避免应用启动时多实例同时迁移”已经通过代码审查或运行验证。
- 确认“只读查询使用 AsNoTracking,并投影成 DTO,减少跟踪和无用列”已经通过代码审查或运行验证。
- 确认“警惕循环内访问导航属性产生 N+1,按场景选择投影、Include 或拆分查询”已经通过代码审查或运行验证。
- 为失败路径、边界条件和回滚方案准备测试或演练记录。
- 上线后观察错误率、延迟和资源消耗,确认变化符合预期。
总结
EF Core 迁移与查询优化实战的关键在于把隐含假设变成可执行的约束,并通过测试、监控和复盘持续验证。先从影响最大的真实场景开始,小步调整并保留回滚能力,通常比一次性大范围改造更安全,也更容易积累可复用的工程经验。