9.29 EFCore 最佳实践
9.29.1 EFCore 高性能
在 Furion
框架,默认推荐使用 EFCore
操作数据库,但很多朋友对 EFCore
使用不当,特意编写此文档说明。
- 尽可能的采用
IRepository/IRepository<TEntity>
仓储方式在构造函数中初始化,避免使用Db.GetRepository<TEntity>
方式。 - 请以异步方式调用所有数据访问 api。
- 检索的数据不是必需的。 编写查询以仅返回当前 HTTP 请求所必需的数据。
- 如果数据可以接受,请考虑缓存经常访问的从数据库或远程服务检索的数据。 使用 MemoryCache 或 microsoft.web.distributedcache ,具体取决于方案。
- 尽量减少网络往返次数。 目标是使用单个调用而不是多个调用来检索所需数据。
- 如果当前请求只有数据查询,请使用无跟踪查询方式。
- 如果请求中含有操作数据时,请不要在 Entity Framework Core 中使用无跟踪查询。 EF Core 可以更有效地返回无跟踪查询的结果。 筛选和聚合 LINQ 查询(例如, .Where 使用.Select、或.Sum 语句),以便数据库执行筛选。
- 对于需要进行复杂逻辑计算查询数据情况,请尽可能在返回查询后再在客户端计算。
- 不要对集合使用投影查询,这可能会导致执行 "N + 1" 个 SQL 查询。
- 使用 ·DbContextPool· 池来管理 DbContext,类似 ADO.NET 的连接池。
- 手动或显式编译的查询 API,允许应用程序缓存查询转换,使其可仅被计算一次并执行多次。
// Create an explicitly compiled query
private static Func<CustomerContext, int, Customer> _customerById =
EF.CompileQuery((CustomerContext db, int id) =>
db.Customers
.Include(c => c.Address)
.Single(c => c.Id == id));
// Use the compiled query by invoking it
using (var db = new CustomerContext())
{
var customer = _customerById(db, 147);
}
9.29.2 反馈与建议
与我们交流
给 Furion 提 Issue。