导读:本期聚焦于小伙伴创作的《C#如何使用EF Core进行增删改查?从入门到精通的完整教程》,敬请观看详情。直接操作数据库时,手写SQL不仅容易拼错字段名,还面临注入风险。EF Core作为微软官方的对象关系映射框架,把数据表映射成C#实体类,用LINQ语法完成持久化。本文从DbContext配置讲起,依次覆盖单条与批量新增、主键与条件删除、跟踪与非跟踪修改、基础查询与关联包含,并给出SaveChanges的事务细节。无论控制台程序还是Web API,只要理解变更跟踪机制,就能用极少代码实现稳定可靠的增删改查,不必再维护冗长SQL脚本。

在C#项目中,EF Core通过对象关系映射让开发者用强类型方式操作数据库。它把数据表转换为实体类,将LINQ查询翻译为对应数据库的SQL,从而屏蔽底层差异。掌握增删改查,核心在于理解DbContext的变更跟踪与SaveChanges的提交机制。

C#如何使用EF Core进行增删改查?从入门到精通的完整教程

一、环境准备与DbContext配置

使用EF Core的第一步是定义实体类和继承DbContext的上下文类。实体类的属性通常对应数据表字段,主键使用Key特性或约定命名Id。DbContext中通过DbSet<T>暴露各个表的集合,并在OnConfiguring中指定数据库提供程序与连接串。

下面以SQLite为例展示最小配置。实际项目中建议将连接串放在配置文件,并使用依赖注入注册上下文,而非在代码中硬编码。注意UseSqlite来自Microsoft.EntityFrameworkCore.Sqlite包,不同数据库需引用对应提供程序。

using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

public class Product
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

public class AppDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        options.UseSqlite("Data Source=app.db");
    }
}

二、新增数据操作

新增分为单条与批量两种常见形式。对于被上下文跟踪的新实体,调用Add或AddRange后,状态会被标记为Added,执行SaveChanges时才会真正生成INSERT语句。若实体未被跟踪,也可先附加再改状态,但一般直接用Add更直观。

下面的代码演示插入单个商品与一次插入多个商品。SaveChanges默认在事务中执行,要么全部成功要么回滚,保证数据一致性。如果需要在插入后获取自增主键,EF Core会在提交后自动将数据库生成的值同步回实体对象。

using (var db = new AppDbContext())
{
    // 单条新增
    var p1 = new Product { Name = "键盘", Price = 99.9m };
    db.Products.Add(p1);
    db.SaveChanges();
    Console.WriteLine("新Id:" + p1.Id);

    // 批量新增
    var list = new List<Product>
    {
        new Product { Name = "鼠标", Price = 59.0m },
        new Product { Name = "显示器", Price = 899.0m }
    };
    db.Products.AddRange(list);
    db.SaveChanges();
}

三、删除数据操作

删除操作必须先让上下文知道要删的实体。常见做法是用主键查询出实体再Remove,适用于需要确认数据存在的场景。若仅按条件删除且不关心实体内容,可借助EF Core的批量删除扩展(如ExecuteDelete)减少查询开销。

传统跟踪删除代码如下。Remove会把状态置为Deleted,SaveChanges发出DELETE。注意若实体未被当前上下文跟踪,需先Attach再Remove,否则会报找不到主键跟踪项。批量删除扩展方法在Microsoft.EntityFrameworkCore.Relational中提供,能直接生成DELETE WHERE,不经过实体物化。

using (var db = new AppDbContext())
{
    // 按主键查询后删除
    var item = db.Products.Find(1);
    if (item != null)
    {
        db.Products.Remove(item);
        db.SaveChanges();
    }

    // 条件批量删除,无需先查询
    db.Products.Where(p => p.Price < 10).ExecuteDelete();
}

四、修改数据操作

修改分为跟踪修改与非跟踪修改。跟踪修改最自然:查询出的实体被上下文监视,改属性后SaveChanges会自动比对快照生成UPDATE。非跟踪场景(如Web层传来的DTO)可用Update附加为Modified状态,但会更新所有列。

以下展示两种方式。第一种利用跟踪自动脏检查,只改变动字段;第二种显式Update,适合断开式环境。若只想更新部分字段,可在非跟踪时借助Entry().Property().IsModified控制,避免多余写列。

using (var db = new AppDbContext())
{
    // 跟踪修改
    var p = db.Products.Find(2);
    if (p != null)
    {
        p.Price = 69.0m;
        db.SaveChanges();
    }

    // 非跟踪修改
    var detached = new Product { Id = 3, Name = "耳机", Price = 199.0m };
    db.Products.Update(detached);
    db.SaveChanges();
}

五、查询数据操作

查询是EF Core最常用能力。LINQ to Entities支持Where、OrderBy、Select、Include等。Include用于预先加载关联表,避免遍历时触发延迟加载导致N+1查询。尽量在数据库端用Select投影所需字段,减少传输量。

下面示例包含条件过滤、排序与关联包含。若Product有Category导航属性,Include会生成LEFT JOIN。AsNoTracking可在只读场景关闭跟踪提升性能。分页用Skip和Take,注意排序稳定后再分页,防止数据错乱。

using (var db = new AppDbContext())
{
    var result = db.Products
        .AsNoTracking()
        .Where(p => p.Price > 50)
        .OrderByDescending(p => p.Price)
        .Skip(0)
        .Take(10)
        .ToList();

    foreach (var p in result)
    {
        Console.WriteLine($"{p.Name} {p.Price}");
    }
}

六、变更跟踪与SaveChanges细节

DbContext维护实体状态机,状态包括Added、Modified、Deleted、Unchanged、Detached。SaveChanges遍历跟踪项,按状态生成命令并批量提交。一次调用默认开启事务,若某条失败整体回滚,因此多步操作无需手动BeginTransaction也能保证原子性。

长生命周期上下文会累积跟踪项导致内存上涨,建议用using块短时持有。对于高并发更新,要注意跟踪冲突与并发令牌(ConcurrencyToken)。合理设计聚合边界,避免把大图全部加载再保存,可显著提升吞吐。

操作推荐方式注意点
新增Add / AddRange自增键提交后回填
删除Remove 或 ExecuteDelete批量删免查询
修改跟踪改属性 / UpdateUpdate更新全列
查询LINQ + AsNoTracking只读关跟踪省资源

七、常见误区与建议

一个典型误区是在循环里反复SaveChanges,导致大量短事务与网络往返。应尽量在业务边界统一提交一次。另一个误区是滥用延迟加载,造成隐藏的多次查询,建议显式Include或投影。

此外,不要将DbContext设为静态单例长期存活,它在多线程下非线程安全。Web应用通过依赖注入使用Scoped生命周期,每次请求一个实例,既安全又方便事务边界控制。掌握这些,就能用EF Core稳健地完成各类增删改查需求。

EF_Core增删改查CSharp修改时间:2026-08-11 05:24:33

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。