EF Core 数据访问三件套:池化 · 仓储 · 不跟踪
今天聊「程序怎么跟数据库打交道」这件事,串起三个核心概念:DbContext、池化工厂、依赖注入。全程用公开技术概念,不涉及任何具体项目/产品。
一、概念:DbContext 是「跟数据库打交道的窗口」
所有查数据、存数据、改数据、删数据的操作,都通过一个叫 DbContext 的对象去办。它就是你和数据库之间的那一个「服务窗口」。
生活类比:你去办事大厅,不管办什么事,都得走到那个窗口前,窗口里的工作人员帮你办。DbContext 就是这个窗口。
二、为什么不每次 new 一个窗口:池化
最简单的做法是「每次要用就 new 一个窗口,用完扔掉」。但造一个窗口是有成本的(要准备一堆内部状态),频繁 new 会浪费。
更好的做法是池化 :造一批窗口放着,谁要用就借一个 ,用完擦干净还回去,下一个人接着用。
生活类比:共享单车。一批车停桩位上,骑完还回桩,下个人接着骑,不用每人买辆新车。
三、工厂与池:管理员和车棚
池化这件事,靠两个角色配合:
- 工厂(IDbContextFactory) = 管理员。你找它借窗口,它从池里拿一个给你。
- 池 = 管理员肚子里的「车棚」,存着那些空闲的窗口。
借的方法就叫 CreateDbContext()------你调它,管理员就从车棚里提一辆(或现造一辆)给你。
四、DbContextOptions:一张电话卡
窗口要干活,得先知道「连哪个数据库」。这个信息装在一个叫 DbContextOptions 的「配置包」里,最重要一条是连接串(地址 + 账号密码)。
顺序是:先填好电话卡(配置包)→ 再造窗口(DbContext)。窗口拿到卡才知道拨哪个号码。
五、依赖注入容器:人事部
那工厂(管理员)从哪来?不是我们手动 new 的,是交给一个「登记本」管:
- 程序启动时,往登记本上写「怎么造管理员」(
AddPooledDbContextFactory)。 - 之后有地方喊「我要个管理员」,**DI 容器(依赖注入容器)**就照登记本造一个派过去。
生活类比:登记本 = 员工登记表;DI 容器 = 人事部;喊「我要管理员」= 某个岗位缺人;派过去的 = 那个管理员。
附录:语法点(示意,泛化)
csharp
// 1. 注册池化工厂(登记「怎么造管理员」)
services.AddPooledDbContextFactory<MyDbContext>(options =>
options.UseMySQL(连接串)
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));
// 2. 造窗口(定义 DbContext,收配置包)
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }
}
// 3. 借窗口(管理员 CreateDbContext 从池里借)
await using var ctx = await factory.CreateDbContextAsync();
三个语法点:
AddPooledDbContextFactory<T>():登记「用池化方式管 T」。DbContextOptions<T>:配置包类型,构造 DbContext 时传进去。CreateDbContextAsync():从池里借一个 DbContext 实例。