EF Core 连接数据库前必须配对 DbContext 和 DbSet,否则编译或运行时报错;DbContext 需继承并配置选项,DbSet 命名用复数;SQLite 路径需绝对或拼接;SaveChanges() 才真正写库,推荐异步;避免客户端求值,开启日志查 SQL;迁移需 Design 包和正确项目指定。

EF Core 连接数据库前必须配对 DbContext 和 DbSet
不配好这两样,连 dotnet run 都可能报错,更别说查数据了。常见错误是只建了实体类,没在 DbContext 里声明 DbSet,结果调用 context.Users 时直接编译失败或运行时报 NullReferenceException。
-
DbContext类必须继承自Microsoft.EntityFrameworkCore.DbContext,且重写OnConfiguring或通过 DI 注入DbContextOptions - 每个要映射的表对应一个
DbSet属性,命名习惯用复数(如public DbSet)Products { get; set; } - 如果用 SQLite,连接字符串里路径要写绝对路径或用
AppContext.BaseDirectory拼接,否则迁移时找不到文件
SaveChanges() 不自动提交事务,async 版本叫 SaveChangesAsync()
很多人以为调了 context.Add(new Order()) 就立刻入库了,其实只是加进变更跟踪器;真正写库靠 SaveChanges()。漏掉这句,数据永远不落地。
- 同步方法阻塞线程,Web API 场景下建议统一用
SaveChangesAsync()配合await - 它默认开启事务,但不会跨多个
SaveChanges调用延续——两次调用之间出异常,第一次的修改已提交,没法回滚 - 批量插入别用循环 +
Add()+SaveChanges(),性能极差;改用context.AddRange()再一次提交
查询时别在 IQueryable 上直接调 .ToList() 或 .First() 前做复杂 C# 运算
EF Core 翻译 SQL 有边界,比如 DateTime.Now.AddDays(7) 能转,但 user.Name.ToUpper().Contains("ADMIN") 会触发客户端求值(ClientEvaluated),小数据看不出问题,大数据量时整张表拉到内存再过滤,CPU 和内存都爆。
- 优先用 EF 支持的函数:比如
EF.Functions.Like()替代string.Contains(),DateTime.UtcNow替代DateTime.Now - 不确定是否服务端执行?打开日志看生成的 SQL:
options.LogTo(Console.WriteLine)加在UseSqlServer后 - 需要复杂逻辑又绕不开客户端处理?显式用
.AsEnumerable()切换上下文,但得清楚这是主动放弃 SQL 下推
迁移命令依赖 Microsoft.EntityFrameworkCore.Tools 包和正确的启动项目
dotnet ef migrations add Init 报 “No project was found” 或 “Unable to retrieve project metadata”,大概率不是命令写错,而是环境没对齐。
- 确保目标项目(含
DbContext的那个)已安装Microsoft.EntityFrameworkCore.Design—— 运行时不需要,但迁移工具强依赖它 - 如果解决方案里有多个项目,
--project和--startup-project必须指定清楚:dotnet ef migrations add Init --project DataProject --startup-project WebApiProject - SQLite 不支持所有迁移操作(比如改列类型),
dotnet ef migrations script生成的 SQL 可能含ALTER COLUMN,直接执行会失败
关系映射看着简单,但外键配置、级联删除策略、索引定义这些细节,一不留神就让 SaveChanges 报错或查不出预期数据。动手前先跑通一个带主从表的最小迁移+查询闭环,比对着文档抄十段代码管用。











