C#怎么使用Dapper连接数据库

来源:站长平台作者:比特币程序员头衔:程序员
导读:本期聚焦于比特币程序员创作的《C#怎么使用Dapper连接数据库》,敬请观看详情。Dapper是.NET平台下轻量高效的ORM框架,很多C#开发者在开发数据访问层时会选择它来替代繁琐的原生ADO.NET操作。本文会详细介绍Dapper的基础使用流程,包括环境准备、数据库连接配置、基本的增删改查操作实现,还会说明Dapper处理参数化查询、复杂对象映射的常用方法。内容从基础到实用场景逐步展开,适合刚接触Dapper的C#开发者快速上手,帮助大家掌握用Dapper简化数据库操作的核心技巧,提升数据访问层的开发效率。

Dapper作为C#生态中备受推崇的轻量级对象关系映射框架,以其卓越的性能和极简的API设计著称。与传统的重量级ORM相比,它不需要繁琐的配置即可快速实现应用程序与数据库的交互。通过扩展ADO.NET的接口,Dapper大幅减少了数据访问层的重复代码编写工作,同时保留了几乎等同于原生SQL的执行效率,成为众多开发者在处理数据库操作时的首选工具。

环境配置与数据库连接构建

在开始使用Dapper之前,首要任务是在项目中引入相关的依赖包。对于基于.NET Core或更高版本的项目,可以通过NuGet包管理器进行安装,或者直接在项目配置文件中添加相应的包引用。这种依赖管理方式能够确保项目始终使用稳定且兼容的版本,为后续的数据访问操作奠定坚实的基础。

以下是.NET项目中添加Dapper依赖的标准配置示例:

<PackageReference Include="Dapper" Version="2.1.35" />

Dapper本身并不负责管理数据库连接池,而是作为ADO.NET的扩展方法存在。因此,开发者需要手动配置数据库连接字符串,并编写相应的方法来实例化数据库连接对象。连接字符串中包含了服务器地址、数据库名称以及身份验证凭证等关键信息,确保应用程序能够安全地定位并访问目标数据库。

在获取连接对象时,必须确保在使用完毕后正确释放资源。利用C#的using语句块可以自动管理连接的生命周期,避免连接泄漏导致的数据库性能问题。以下代码展示了如何配置连接字符串并封装获取SQL Server连接对象的标准方法。

using System.Data;
using System.Data.SqlClient;
using Dapper;

// 数据库连接字符串,实际使用时需替换为真实的数据库地址和凭证
private static string connectionString = "Server=127.0.0.1;Database=TestDB;User Id=sa;Password=123456;";

// 获取数据库连接的方法
public static IDbConnection GetConnection()
{
    return new SqlConnection(connectionString);
}

核心数据操作与参数化安全

在确立了数据库连接之后,即可开展基础的数据操作。Dapper提供了丰富的扩展方法来简化增删改查流程。对于查询操作,开发者只需定义与数据库表结构相对应的实体类,Dapper便会利用反射机制将查询结果自动映射为实体对象集合。这种机制极大地简化了数据读取的代码逻辑,使得开发者能够专注于业务层面的数据处理。

假设数据库中存在一张User表,包含Id、UserName、Age和CreateTime字段,对应的实体类与查询操作实现如下:

public class User
{
    public int Id { get; set; }
    public string UserName { get; set; }
    public int Age { get; set; }
    public DateTime CreateTime { get; set; }
}

public static List<User> GetAllUsers()
{
    using (IDbConnection conn = GetConnection())
    {
        string sql = "SELECT Id, UserName, Age, CreateTime FROM User";
        return conn.Query<User>(sql).ToList();
    }
}

除了查询,数据的插入、更新和删除同样依赖于Dapper提供的方法。插入数据时,若需要获取数据库自动生成的主键,可以结合数据库特定的函数来实现。而在执行更新和删除操作时,只需构建相应的SQL语句并传入受影响的条件参数即可。这些操作均通过执行SQL命令并返回受影响的行数来反馈执行结果。

// 插入用户并获取自增主键
public static int AddUser(User user)
{
    using (IDbConnection conn = GetConnection())
    {
        string sql = "INSERT INTO User (UserName, Age, CreateTime) VALUES (@UserName, @Age, @CreateTime); SELECT CAST(SCOPE_IDENTITY() as int)";
        return conn.ExecuteScalar<int>(sql, user);
    }
}

// 更新用户年龄
public static int UpdateUserAge(int userId, int newAge)
{
    using (IDbConnection conn = GetConnection())
    {
        string sql = "UPDATE User SET Age = @NewAge WHERE Id = @UserId";
        return conn.Execute(sql, new { UserId = userId, NewAge = newAge });
    }
}

// 删除指定用户
public static int DeleteUser(int userId)
{
    using (IDbConnection conn = GetConnection())
    {
        string sql = "DELETE FROM User WHERE Id = @UserId";
        return conn.Execute(sql, new { UserId = userId });
    }
}

在进行上述所有数据操作时,必须严格遵循参数化查询的原则。直接拼接字符串来构建SQL语句不仅会导致代码可读性下降,更会引入严重的SQL注入安全漏洞。Dapper默认支持参数化查询,通过匿名对象或实体对象传递参数,能够确保用户输入被安全地处理为数据值而非可执行的SQL指令,从而保障数据库的绝对安全。

// 错误写法:直接拼接字符串,存在极高的SQL注入风险
// string sql = "SELECT * FROM User WHERE UserName = '" + userName + "'";

// 正确写法:使用参数化查询,确保数据安全
string sql = "SELECT * FROM User WHERE UserName = @UserName";
var user = conn.QueryFirstOrDefault<User>(sql, new { UserName = userName });

高级特性与复杂对象映射

在实际的业务场景中,数据往往不是孤立存在的,多表关联查询是不可避免的需求。当查询结果涉及多个实体对象时,简单的单表映射便无法满足要求。Dapper为此提供了强大的多实体映射功能,允许开发者在一次查询中将结果集拆分并映射到不同的对象中,从而构建出具有层级关系的复杂对象模型。

实现多表映射的核心在于使用Query方法的重载版本,并通过splitOn参数明确指定结果集中的分割列。分割列之前的字段将被映射到第一个实体对象,而之后的字段则映射到后续的实体对象。为了处理一对多的关系,通常需要借助字典来缓存已创建的主对象,并在遍历结果集时动态地向其集合属性中添加子对象。

public class User
{
    public int Id { get; set; }
    public string UserName { get; set; }
    public List<Order> Orders { get; set; }
}

public class Order
{
    public int OrderId { get; set; }
    public int UserId { get; set; }
    public decimal Amount { get; set; }
}

public static List<User> GetUserWithOrders()
{
    using (IDbConnection conn = GetConnection())
    {
        string sql = @"SELECT u.Id, u.UserName, o.OrderId, o.UserId, o.Amount 
                      FROM User u 
                      LEFT JOIN Order o ON u.Id = o.UserId";
        var userDict = new Dictionary<int, User>();
        
        // splitOn指定分割列,OrderId之前的列映射到User,之后的映射到Order
        var result = conn.Query<User, Order, User>(sql, (user, order) =>
        {
            if (!userDict.TryGetValue(user.Id, out User currentUser))
            {
                currentUser = user;
                currentUser.Orders = new List<Order>();
                userDict.Add(currentUser.Id, currentUser);
            }
            if (order != null)
            {
                currentUser.Orders.Add(order);
            }
            return currentUser;
        }, splitOn: "OrderId").Distinct().ToList();
        
        return result;
    }
}

通过上述对Dapper环境配置、基础操作以及高级映射特性的详细解析,可以看出该框架在保持轻量级的同时,提供了极其灵活且强大的数据访问能力。掌握这些核心知识点,能够帮助开发者在C#项目中构建出高效、安全且易于维护的数据访问层。建议在后续的学习与实践中,进一步探索Dapper在事务处理、异步操作以及存储过程调用等方面的应用,以全面提升数据库编程的综合技能。

DapperORMC#_database修改时间:2026-06-19 15:39:43

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