Dapper在C#中应用详解

Dapper在C#中应用详解

编码文章call10242025-06-13 2:16:384A+A-

Dapper是一个轻量级的ORM(Object Relational Mapper)工具,专为.NET框架设计,不过个人还是喜欢SqlSugar。它提供了一种高速的,在一定程度上接近手写SQL语句性能的数据库访问方法。它因其简单性和灵活性而广受欢迎,非常适合需要对性能有高要求但又不希望处理复杂的ORM框架,比如Entity Framework的场景。

Dapper的特点

1. 轻量级

Dapper是一个单文件库,集成进项目非常简单,不会像其他大型ORM框架那样增加额外的负担。

2. 性能高效

Dapper直接使用ADO.NET,即其底层仅是对ADO.NET的封装,这保证了非常高的执行效率,几乎与直接使用raw ADO.NET相当。

3. 简单明了

Dapper的API设计简洁易懂,而且它只做必要的工作,绝不过度抽象化。开发者能够在需要时直接编写SQL查询,获取完整的功能控制。

4. 灵活性

由于直接编写SQL语句,Dapper能直接利用数据库特性例如存储过程、复杂查询等,可维护性高,也能与其他ORM框架并行使用。

Dapper的基本用法

环境准备

在开始使用Dapper之前,首先需要确保你的项目中有Dapper这个库。可以使用NuGet包管理器来安装:

Install-Package Dapper

基本操作示例

创建数据库连接

using System.Data.SqlClient;

// Connection string
string connectionString = "Server=localhost;Database=testdb;User Id=sa;Password=123;";

// 创建 SQL 连接
using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    // 这里可以进行数据库操作
}

查询操作

Dapper最常用的操作之一是查询数据库。这包括简单的SELECT语句以及复杂的多表JOIN。

using Dapper;
using System.Collections.Generic;

// 定义数据模型
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

// 查询数据
string sqlQuery = "SELECT * FROM Person";

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    IEnumerable<Person> people = connection.Query<Person>(sqlQuery);
    
    foreach (var person in people)
    {
        Console.WriteLine(#34;ID: {person.Id}, Name: {person.Name}, Age: {person.Age}");
    }
}

插入操作

你还可以使用Dapper进行插入操作:

string insertQuery = "INSERT INTO Person (Name, Age) VALUES (@Name, @Age)";

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    var affectedRows = connection.Execute(insertQuery, new { Name = "John Doe", Age = 30 });
    Console.WriteLine(#34;Rows inserted: {affectedRows}");
}

更新操作

更新数据库记录同样简单:

string updateQuery = "UPDATE Person SET Age = @Age WHERE Name = @Name";

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    var affectedRows = connection.Execute(updateQuery, new { Name = "John Doe", Age = 31 });
    Console.WriteLine(#34;Rows updated: {affectedRows}");
}

删除操作

删除操作也非常直观:

string deleteQuery = "DELETE FROM Person WHERE Name = @Name";

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    var affectedRows = connection.Execute(deleteQuery, new { Name = "John Doe" });
    Console.WriteLine(#34;Rows deleted: {affectedRows}");
}

多结果集查询

CREATE PROCEDURE GetPersonAndOrders
    @PersonId INT
AS
BEGIN
    SELECT Id, Name
    FROM Person
    WHERE Id = @PersonId

    SELECT Id, PersonId, Amount
    FROM [Order]
    WHERE PersonId = @PersonId

END

有时候,我们可能需要从一个查询中获取多个结果集,Dapper可以轻松处理这种情况。

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    var personIdParameter = new { PersonId = 1 }; // 假设要查询的 PersonId 为 1

    using (var multi = connection.QueryMultiple("GetPersonAndOrders", personIdParameter, commandType: CommandType.StoredProcedure))
    {
        var person = multi.Read<Person>().FirstOrDefault();
        var orders = multi.Read<Order>().ToList();

        if (person != null)
        {
            Console.WriteLine(#34;Person: {person.Name}");

            foreach (var order in orders)
            {
                Console.WriteLine(#34;Order ID: {order.OrderId}, Amount: {order.Amount}");
            }
        }
        else
        {
            Console.WriteLine("No person found with the given ID.");
        }
    }
}

存储过程

CREATE PROCEDURE GetPersonById
    @Id INT
AS
BEGIN
    SELECT Id, Name, Age
    FROM Person
    WHERE Id = @Id;
END

Dapper直接支持调用存储过程,这使得它在使用数据库的内置功能时非常方便。

string storedProcedure = "GetPersonById";
var parameters = new { Id = 1 }; // 假设要查询的人员 ID 为1

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();

    try
    {
        var person = connection.QueryFirstOrDefault<Person>(storedProcedure, parameters, commandType: CommandType.StoredProcedure);

        if (person != null)
        {
            Console.WriteLine(#34;Person: {person.Name}, Age: {person.Age}");
        }
        else
        {
            Console.WriteLine("No person found with the given ID.");
        }
    }
    catch (SqlException ex)
    {
        Console.WriteLine(#34;SQL Error: {ex.Message}");
    }
    catch (Exception ex)
    {
        Console.WriteLine(#34;An error occurred: {ex.Message}");
    }
}

事务支持

Dapper支持数据库事务,可以在多个操作中维护完整性和一致性。

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    using (var transaction = connection.BeginTransaction())
    {
        try
        {
            string insertPersonQuery = "INSERT INTO Person (Name, Age) VALUES (@Name, @Age)";
            string insertOrderQuery = "INSERT INTO [Order] (PersonId, Amount) VALUES (@PersonId, @Amount)";

            connection.Execute(insertPersonQuery, new { Name = "Jane Doe", Age = 27 }, transaction);
            connection.Execute(insertOrderQuery, new { PersonId = 2, Amount = 200 }, transaction);

            transaction.Commit();
            Console.WriteLine("Transaction committed successfully.");
        }
        catch (Exception ex)
        {
            transaction.Rollback();
            Console.WriteLine(#34;Transaction rolled back: {ex.Message}");
        }
    }
}

映射一对多关系

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public List<Order> Orders { get; set; }

    public Person()
    {
        Orders = new List<Order>();
    }
}

Dapper允许我们在一次查询中映射父/子关系,非常适用于表之间有关系的情况。

string sql = @"
SELECT * FROM Person p
LEFT JOIN [Order] o ON p.Id = o.PersonId
WHERE p.Id = @Id";

using (SqlConnection connection = new SqlConnection(connectionString))
{
    var lookup = new Dictionary<int, Person>();

    connection.Query<Person, Order, Person>(sql, (person, order) =>
    {
        if (!lookup.TryGetValue(person.Id, out var foundPerson))
        {
            foundPerson = person;
            foundPerson.Orders = new List<Order>();
            lookup.Add(foundPerson.Id, foundPerson);
        }

        if (order != null)
        {
            foundPerson.Orders.Add(order);
        }

        return foundPerson;
    }, new { Id = 1 });

    var result = lookup.Values.FirstOrDefault();

    Console.WriteLine(#34;Person: {result.Name}");

    foreach (var order in result.Orders)
    {
        Console.WriteLine(#34;Order ID: {order.OrderId}, Amount: {order.Amount}");
    }
}

批量插入

虽然Dapper没有直接的批量插入功能,但我们可以通过组合SQL查询或使用数据库特定功能来实现。

var people = new List<Person>
{
    new Person { Name = "Alice", Age = 25 },
    new Person { Name = "Bob", Age = 30 }
};

string sql = "INSERT INTO Person (Name, Age) VALUES (@Name, @Age)";

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    var affectedRows = connection.Execute(sql, people);
    Console.WriteLine(#34;Rows inserted: {affectedRows}");
}

这些例子展示了Dapper的强大和灵活性,使其能够应对从简单到复杂的各种数据库操作。无论是处理多结果集、事务、还是关系映射,Dapper都能提供高效的解决方案。

总结

Dapper在保持轻量级和性能优势的同时,提供了强大的数据库交互功能。对于需要高效进行数据库操作但并不适合全栈ORM(如Entity Framework)的项目,Dapper是一个理想的选择。此外,它与其他框架的兼容性,确保了开发者能够灵活地选择最佳的组合工具进行开发。

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4