0Pricing
C# Academy · 课时

DbContext 与 DbSet 基础

设置 DbContext,定义实体,配置连接字符串,并运行第一个查询。

DbContext 与 DbSet 基础 是 CoddyKit 上的免费 C# Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 4 节课。

什么是 Entity Framework Core

EF Core 是官方的 .NET 对象关系映射器(ORM)。它将 C# 类(实体)映射到数据库表,并允许您使用 LINQ 查询和保存数据——对于大多数操作都无需编写 SQL。

定义实体

实体是一个普通的 C# 类,其属性会映射到数据库列。按照约定,名为 Id 或 <TypeName>Id 的属性会成为主键。

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public decimal Price { get; set; }
    public int Stock { get; set; }
    public DateTime CreatedAt { get; set; }
}

创建 DbContext

DbContext 是访问数据库的入口。它为每个实体保存 DbSet<T> 属性,并管理连接、变更跟踪和事务。

using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options)
        : base(options) { }

    public DbSet<Product> Products => Set<Product>();
    public DbSet<Order>   Orders   => Set<Order>();
}

使用 DI 注册 DbContext

调用 AddDbContext,将上下文注册为作用域服务并配置数据库提供程序。

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("Default")));

// For SQLite (great for development/testing):
// options.UseSqlite("Data Source=app.db");

使用 DbSet 的基本查询

DbSet<T> 提供 LINQ 运算符。查询在枚举之前不会执行(await ...ToListAsync())。这称为延迟执行。

public class ProductService
{
    private readonly AppDbContext _db;
    public ProductService(AppDbContext db) => _db = db;

    public async Task<List<Product>> GetExpensiveAsync(decimal minPrice)
    {
        return await _db.Products
            .Where(p => p.Price >= minPrice)
            .OrderBy(p => p.Name)
            .ToListAsync();
    }
}

按主键查找

FindAsync 会先检查本地更改跟踪器缓存,然后才访问数据库。按主键查询时使用它,可以避免不必要的数据库往返。

var product = await _db.Products.FindAsync(42);
if (product is null)
    throw new KeyNotFoundException("Product not found");

// For complex keys, pass all key values:
var orderLine = await _db.OrderLines.FindAsync(orderId, productId);

添加新记录

调用 Add 将实体加入待插入队列,然后调用 SaveChangesAsync 提交。EF Core 会生成 INSERT SQL,并填充自动生成的 Id。

var product = new Product
{
    Name = "Mechanical Keyboard",
    Price = 149.99m,
    Stock = 50,
    CreatedAt = DateTime.UtcNow
};

_db.Products.Add(product);
await _db.SaveChangesAsync();

Console.WriteLine(product.Id); // Auto-generated PK

更新记录

由 EF Core 加载的实体会被跟踪。直接修改属性,然后调用 SaveChangesAsync——EF Core 会检测更改并生成经过优化的 UPDATE 语句。

var product = await _db.Products.FindAsync(42);
if (product is not null)
{
    product.Price = 129.99m;
    product.Stock -= 1;
    await _db.SaveChangesAsync(); // UPDATE Products SET Price=...
}

删除记录

调用 Remove 将实体标记为待删除,然后调用 SaveChangesAsync。对于批量删除,可以使用 ExecuteDeleteAsync(.NET 7+),而无需加载实体。

// Delete a tracked entity
_db.Products.Remove(product);
await _db.SaveChangesAsync();

// Bulk delete without loading (EF Core 7+)
await _db.Products
    .Where(p => p.Stock == 0)
    .ExecuteDeleteAsync();

使用流式 API 配置

重写 OnModelCreating,使用流式 API 配置实体,包括表名、列类型、约束、索引和关系。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>(entity =>
    {
        entity.ToTable("products");
        entity.Property(p => p.Name).IsRequired().HasMaxLength(200);
        entity.Property(p => p.Price).HasColumnType("decimal(18,2)");
        entity.HasIndex(p => p.Name);
    });
}

实战:使用 DbContext 的仓储

典型的仓储会封装 DbContext,集中管理数据访问逻辑,并将查询细节排除在服务类之外。

public class ProductRepository : IProductRepository
{
    private readonly AppDbContext _db;
    public ProductRepository(AppDbContext db) => _db = db;

    public async Task<Product?> GetByIdAsync(int id)
        => await _db.Products.AsNoTracking().FirstOrDefaultAsync(p => p.Id == id);

    public async Task<List<Product>> SearchAsync(string query)
        => await _db.Products
            .Where(p => p.Name.Contains(query))
            .AsNoTracking()
            .ToListAsync();
}

快速检查

使用 EF Core 查询时,AsNoTracking() 的作用是什么?

回顾:DbContext 与 DbSet 基础

核心要点:

  • DbContext 是与数据库交互的会话;DbSet<T> 表示一张表
  • 在 DI 中使用 AddDbContext 注册;默认情况下它是作用域服务
  • LINQ 查询采用延迟执行——使用 ToListAsync、FirstOrDefaultAsync 执行
  • 更改跟踪通过 SaveChangesAsync 实现自动 UPDATE/DELETE
  • 对于只读查询,使用 AsNoTracking() 可以提升性能

常见问题解答

「DbContext 与 DbSet 基础」课时是免费的吗?

是的 — 「DbContext 与 DbSet 基础」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 4 节课。

「DbContext 与 DbSet 基础」这节课中我会学到什么?

设置 DbContext,定义实体,配置连接字符串,并运行第一个查询。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C# Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「DbContext 与 DbSet 基础」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C# Academy 课中编写并运行代码吗?

能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. DbContext 与 DbSet 基础
  2. 迁移与架构管理
  3. 使用 EF Core 执行 CRUD 操作
  4. 关系:一对多与多对多
← 返回 C# Academy