C#Dapper 超全详细使用教程(从入门到进阶)

C# Dapper 超全详细使用教程(从入门到进阶)

Dapper 是一款专为.NET设计的轻量级、高性能ORM(对象关系映射)框架,核心是扩展 ADO.NET 的 IDbConnection 接口,摒弃了复杂的配置和冗余的上下文管理,以极简的API封装原生SQL操作,性能接近手写ADO.NET,同时兼顾开发效率,是.NET项目中高频使用的数据持久化框架。本文将从基础概念、环境搭建、核心原理、基础CRUD、高级功能、最佳规范、优缺点等方面,全方位讲解Dapper的完整使用方案。

一、Dapper 核心基础介绍

1.1 核心原理

Dapper 基于 ADO.NET 底层封装,通过扩展方法增强 IDbConnection 接口能力,核心工作流程简单高效:

  1. 建立数据库连接:依托原生ADO.NET的IDbConnection接口创建数据库连接;

  2. 执行SQL语句:通过Dapper封装的扩展方法执行原生SQL或存储过程;

  3. 自动结果映射:将数据库查询结果集自动映射为C#实体对象或集合。

其高性能的核心原因:无复杂的实体跟踪、无需动态生成SQL、内置SQL查询计划缓存,最大程度减少性能开销。

1.2 Dapper 与主流数据库框架对比

为清晰区分各框架适用场景,以下是Dapper与EF、NHibernate、原生ADO.NET的特性对比:

特性 Dapper Entity Framework NHibernate ADO.NET
性能 极高(接近原生) 中等 中等 极高
易用性 高、API简洁 高、开箱即用 中等、配置繁琐 低、代码冗余
实体映射能力 基础强类型映射 丰富、全自动映射 丰富、全自动映射 无、手动映射
学习曲线 极低 中等 较高
事务支持 完整支持 完整支持 完整支持 原生支持
LINQ支持 不支持 全面支持 全面支持 不支持
配置灵活性 极高、完全掌控SQL 中等、封装度高 高、自定义性强 极高

二、环境准备与基础配置

2.1 安装Dapper NuGet包

项目使用Dapper前,必须安装官方NuGet包,提供三种安装方式:

  1. Visual Studio可视化安装:右键项目 → 管理NuGet程序包 → 搜索「Dapper」安装;

  2. 包管理器控制台:Install-Package Dapper

  3. .NET CLI命令:dotnet add package Dapper

2.2 引入核心命名空间

以SQL Server为例,需引入以下必备命名空间,其他数据库需替换对应连接命名空间:

using System.Data;                  // 数据库操作核心接口
using System.Data.SqlClient;       // SQL Server连接专属命名空间
using Dapper;                      // Dapper核心扩展命名空间

补充:MySQL对应命名空间为 MySqlConnector,PostgreSQL对应 Npgsql

2.3 数据库连接配置

Dapper无连接池封装,完全依赖原生IDbConnection,标准使用方式为静态连接字符串+using自动释放连接,避免资源泄露:

// 数据库连接字符串(根据自身数据库配置修改)
private static readonly string _connectionString = 
    "Server=你的服务器名;Database=你的数据库名;Uid=用户名;Pwd=密码;TrustServerCertificate=True;";

// 标准连接使用模板
using (IDbConnection dbConnection = new SqlConnection(_connectionString))
{
    dbConnection.Open(); // 显式打开连接(可控性更强,推荐使用)
    // 所有数据库操作代码写在此代码块中
}

三、Dapper 基础CRUD操作(核心入门)

Dapper核心方法分为两类:Query系列(查询)Execute(增删改),全程支持参数化查询,杜绝SQL注入。

3.1 定义对应数据库实体类

实体类字段建议与数据库表字段一致,字段不一致时可通过[Column("数据库字段名")] 特性映射:

public class User
{
    public int Id { get; set; }         // 主键ID
    public string UserName { get; set; }// 用户名
    public int Age { get; set; }        // 年龄
    public DateTime CreateTime { get; set; } // 创建时间
}

3.2 查询操作(单条/多条)

3.2.1 查询多条数据

使用 Query<T>() 方法,返回实体集合:

/// <summary>
/// 查询所有用户
/// </summary>
public List<User> GetAllUsers()
{
    using (IDbConnection db = new SqlConnection(_connectionString))
    {
        db.Open();
        string sql = "SELECT Id, UserName, Age, CreateTime FROM Users;";
        // 自动映射为User实体列表
        List<User> userList = db.Query<User>(sql).ToList();
        return userList;
    }
}

3.2.2 查询单条数据

使用 QueryFirstOrDefault<T>() 方法,无数据返回null,支持参数化查询:

/// <summary>
/// 根据ID查询单个用户
/// </summary>
public User GetUserById(int userId)
{
    using (IDbConnection db = new SqlConnection(_connectionString))
    {
        db.Open();
        // @Id为参数占位符,Dapper自动映射匿名对象参数
        string sql = "SELECT Id, UserName, Age, CreateTime FROM Users WHERE Id = @Id;";
        User user = db.QueryFirstOrDefault<User>(sql, new { Id = userId });
        return user;
    }
}

3.3 插入操作

使用 Execute() 方法,返回受影响的数据库行数,支持实体对象自动参数映射:

/// <summary>
/// 新增用户数据
/// </summary>
public int InsertUser(User newUser)
{
    using (IDbConnection db = new SqlConnection(_connectionString))
    {
        db.Open();
        string sql = @"INSERT INTO Users (UserName, Age, CreateTime) 
                       VALUES (@UserName, @Age, @CreateTime);";
        // 直接传入实体对象,自动匹配参数
        int affectedRows = db.Execute(sql, newUser);
        return affectedRows;
    }
}

3.4 更新操作

同样使用 Execute() 方法,根据条件更新数据:

/// <summary>
/// 更新用户信息
/// </summary>
public int UpdateUser(User updateUser)
{
    using (IDbConnection db = new SqlConnection(_connectionString))
    {
        db.Open();
        string sql = @"UPDATE Users 
                       SET UserName = @UserName, Age = @Age 
                       WHERE Id = @Id;";
        int affectedRows = db.Execute(sql, updateUser);
        return affectedRows;
    }
}

3.5 删除操作

通过 Execute() 实现条件删除,支持匿名对象传参:

/// <summary>
/// 根据ID删除用户
/// </summary>
public int DeleteUser(int userId)
{
    using (IDbConnection db = new SqlConnection(_connectionString))
    {
        db.Open();
        string sql = "DELETE FROM Users WHERE Id = @Id;";
        int affectedRows = db.Execute(sql, new { Id = userId });
        return affectedRows;
    }
}

3.6 存储过程调用

Dapper支持直接调用数据库存储过程,只需指定命令类型为存储过程:

using (IDbConnection db = new SqlConnection(_connectionString))
{
    // 调用名为GetStudentById的存储过程,传入参数
    var result = db.Query<User>("GetUserById", 
        new { Id = 1 }, 
        commandType: CommandType.StoredProcedure).FirstOrDefault();
}

四、Dapper 高级进阶功能

除基础CRUD外,Dapper支持多表映射、事务、批量操作、动态查询等复杂场景,满足企业级开发需求。

4.1 多表关联映射(一对一/一对多)

支持多表联查,将多表结果自动映射到嵌套实体,通过 splitOn 指定分割字段:

// 学生实体(嵌套班级实体)
public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public Class Class { get; set; }
}
// 班级实体
public class Class
{
    public int Id { get; set; }
    public string ClassName { get; set; }
}

// 多表联查映射
string sql = "SELECT * FROM Students s INNER JOIN Classes c ON s.ClassId = c.Id";
var studentDict = new Dictionary<int, Student>();

using (IDbConnection db = new SqlConnection(_connectionString))
{
    var studentList = db.Query<Student, Class, Student>(sql, 
        (student, cls) => 
        {
            student.Class = cls;
            return student;
        }, splitOn: "Id").Distinct().ToList();
}

4.2 事务处理(保证数据一致性)

Dapper完全兼容ADO.NET事务,支持多操作原子执行,要么全部成功,要么全部回滚:

using (IDbConnection db = new SqlConnection(_connectionString))
{
    db.Open();
    // 开启事务
    using (var transaction = db.BeginTransaction())
    {
        try
        {
            // 执行新增
            string insertSql = "INSERT INTO Students (Name, Age) VALUES (@Name, @Age)";
            db.Execute(insertSql, new { Name = "John", Age = 22 }, transaction);

            // 执行更新
            string updateSql = "UPDATE Students SET Age = @Age WHERE Name = @Name";
            db.Execute(updateSql, new { Age = 23, Name = "John" }, transaction);

            // 提交事务
            transaction.Commit();
        }
        catch
        {
            // 异常回滚
            transaction.Rollback();
        }
    }
}

4.3 批量数据操作

Dapper支持直接传入实体集合,一次性完成批量新增/修改,性能高效:

using (IDbConnection db = new SqlConnection(_connectionString))
{
    string sql = "INSERT INTO Students (Name, Age) VALUES (@Name, @Age)";
    // 实体集合批量插入
    var studentList = new List<Student>
    {
        new Student { Name = "John", Age = 22 },
        new Student { Name = "Jane", Age = 24 },
        new Student { Name = "Mark", Age = 26 }
    };
    // 批量执行,无需循环调用
    db.Execute(sql, studentList);
}

4.4 动态对象查询

适用于查询结果结构不固定、无需定义实体类的场景,使用dynamic动态接收数据:

using (IDbConnection db = new SqlConnection(_connectionString))
{
    string sql = "SELECT Name, Age FROM Students";
    // 动态对象接收结果
    var studentList = db.Query<dynamic>(sql).ToList();
    foreach (var student in studentList)
    {
        Console.WriteLine($"姓名:{student.Name},年龄:{student.Age}");
    }
}

4.5 查询缓存优化

Dapper内置查询缓冲机制,开启buffered可缓存查询结果,减少重复数据库请求开销(默认开启):

using (IDbConnection db = new SqlConnection(_connectionString))
{
    string sql = "SELECT * FROM Students";
    // 开启结果缓存,提升重复查询性能
    var studentList = db.Query<Student>(sql, buffered: true).ToList();
}

五、跨数据库适配方案

Dapper 无数据库绑定特性,可无缝适配主流数据库,仅需替换NuGet包、连接对象、连接字符串

  • MySQL:安装 MySqlConnector 包,使用 MySqlConnection 连接对象;

  • PostgreSQL:安装 Npgsql 包,使用 NpgsqlConnection 连接对象;

  • SQLite:安装 System.Data.SQLite 包,使用 SQLiteConnection 连接对象。

六、核心使用规范与最佳实践

  1. 强制使用参数化查询:所有动态条件必须使用 @参数占位符,杜绝字符串拼接SQL,彻底防止SQL注入;

  2. using托管连接资源:所有IDbConnection对象必须包裹using语句,自动释放数据库连接,避免连接池泄露;

  3. 区分核心方法用途:Query系列方法仅用于查询,Execute方法统一用于增、删、改操作;

  4. 优先显式打开连接:手动调用Open(),相比Dapper自动打开连接,代码可控性更强,便于事务和批量操作;

  5. 规范实体映射:尽量保持实体属性与数据库字段一致,不一致时使用[Column]特性显式映射。

七、Dapper 优缺点总结与适用场景

7.1 核心优势

  • 性能极致:无多余封装,性能接近原生ADO.NET,远超EF等重型框架;

  • 轻量无侵入:体积小、零配置、学习成本极低,快速集成;

  • 灵活性极强:完全掌控原生SQL,支持复杂查询、存储过程、批量操作;

  • 安全性高:原生支持参数化查询,杜绝SQL注入风险;

  • 兼容性好:支持所有主流关系型数据库,支持事务、缓存、多表映射。

7.2 局限性

  • 不支持LINQ查询,需手动编写SQL,复杂查询需自行维护SQL语句;

  • 无实体变化跟踪、级联操作等高级ORM功能;

  • 自动映射能力有限,复杂多对多关系需手动配置映射逻辑。

7.3 适用场景

适合中小型项目、高性能数据接口、老旧项目改造、需要精准控制SQL的场景;不适合超大型复杂业务、依赖全自动ORM映射、需要大量LINQ查询的项目。

八、全文总结

Dapper 以“轻量、高效、灵活”为核心优势,平衡了原生ADO.NET的高性能和传统ORM的易用性。其核心使用逻辑简单:安装NuGet包→配置数据库连接→通过Query/Execute实现CRUD→借助高级功能适配复杂场景。在实际开发中,只要遵循参数化查询、using资源释放等规范,即可高效、稳定地完成各类数据库操作,是.NET生态中不可或缺的数据持久化工具。

posted @ 2026-06-09 15:43  人生就是修炼  阅读(73)  评论(0)    收藏  举报