发布于2026-07-23 阅读(0)
扫一扫,手机访问
在实际开发中,EFCore 的实体属性配置和 DbContext 的管理,是绕不开的核心话题。把这两块吃透了,数据层的开发效率就能上一个台阶。下面就来拆解一下具体的配置方式和用法。
实体属性配置,说白了就是定义模型和数据库之间的映射关系。EFCore 给了我们两种选择:数据注解 和 Fluent API。两种方式各有适用场景,下面逐一来看。
这种方式最直接——在实体类上用特性(Attributes)来声明配置,适合简单场景,比如主键、非空、长度限制之类的。
public class Product
{
[Key] // 主键
public int Id { get; set; }
[Required, MaxLength(100)] // 非空且最大长度100
public string Name { get; set; }
[ForeignKey("CategoryId")] // 外键
public int CategoryId { get; set; }
public Category Category { get; set; }
}
常用注解一览:
[Key]:指定主键
[Required]:非空约束
[MaxLength(length)]:最大长度
[ForeignKey]:配置外键关系
[Table("TableName")]:自定义表名
如果觉得数据注解会污染实体类,或者需要更复杂的配置(比如复合主键、继承映射),那 Fluent API 就是更好的选择。它在 DbContext 的 OnModelCreating 方法里集中配置,维护起来更清晰。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity(entity =>
{
entity.HasKey(p => p.Id); // 主键
entity.Property(p => p.Name)
.IsRequired()
.HasMaxLength(100);
entity.HasOne(p => p.Category) // 一对一/多关系
.WithMany(c => c.Products)
.HasForeignKey(p => p.CategoryId);
});
}
常用配置方法:
HasKey():定义主键
Property().IsRequired():非空约束
HasIndex():创建索引
HasOne().WithMany():配置导航关系
优势很明显:
所有配置集中管理,实体类保持干净,不会被各种注解占满。
支持复杂场景,比如复合主键、继承映射等,这些是数据注解搞不定的。
DbContext 是 EFCore 的心脏,负责数据库连接、查询、事务管理等一系列核心操作。理解它的生命周期和用法,是写好数据访问层的关键。
需要派生一个类继承 DbContext,然后通过 DbSet 属性暴露实体集合。
public class AppDbContext : DbContext
{
public DbSet Products { get; set; }
public DbSet Categories { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlServer("Your_Connection_String");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Fluent API 配置
}
}
在 ASP.NET Core 中,通过依赖注入来管理上下文生命周期是最常见的做法。
// Startup.cs services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("Default")));
作用域(Scoped):这是默认选项,每个请求生成一个实例,既保证了线程安全,又避免了资源浪费。
需要特别注意的是,不要长时间持有 DbContext 实例,否则容易导致内存泄漏——用完即弃才是正道。
查询:
var products = await _context.Products.Where(p => p.Price > 50).ToListAsync();
保存变更:
_context.Products.Add(newProduct); await _context.Sa veChangesAsync();
关键方法:
Add()、Remove():用于跟踪实体状态
Sa veChangesAsync():提交事务,将变更写入数据库
AsNoTracking():如果只是读取数据不修改,禁用变更跟踪能显著提升查询速度。
DbContext 池:复用上下文实例,减少重复创建的开销,尤其在高并发场景下很有用。
services.AddDbContextPool(...);
EFCore 5.0 之后,多对多的配置变得简洁多了,直接用 Fluent API 配上中间表就行。
modelBuilder.Entity() .HasMany(p => p.Tags) .WithMany(t => t.Posts) .UsingEntity(j => j.ToTable("PostTags"));
TPH(Table-Per-Hierarchy)模式是默认的继承映射方式,所有子类共享一张表,用鉴别器区分。
modelBuilder.Entity() .HasDiscriminator ("BlogType") .HasValue ("Standard") .HasValue ("RSS");
这个功能非常实用,比如软删除场景,可以在模型级别自动应用查询条件,而不需要每个查询都手动加 Where 条件。
modelBuilder.Entity().HasQueryFilter(p => !p.IsDeleted);
数据注解 vs. Fluent API 怎么选?
简单配置(主键、非空、长度)用数据注解,代码更直观;复杂场景(复合主键、多对多、继承映射)果断用 Fluent API,避免注解满天飞。
DbContext 线程安全
保证每个请求使用独立的实例,这是最基本的要求。依赖注入的 Scoped 模式正好满足这一点。
迁移(Migrations)
通过 dotnet ef migrations add 生成数据库架构变更,配合 Update-Database 或自动迁移,保持代码和数据库同步。
性能陷阱
千万别在循环里频繁调用 Sa veChanges(),那会带来灾难性的性能开销。批量操作尽量一次性提交。
使用 Include() 预加载关联数据,避免 N+1 查询问题。如果只需要部分字段,还可以用 Select() 投影。
把 EFCore 的属性配置和 DbContext 管理理清楚,数据层开发效率会有质的提升。合理选择配置方式,结合依赖注入和性能优化技巧,就能构建出既高效又稳健的 ASP.NET Core 应用。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8