C# 中Dapper轻量级ORM 的应用详解
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
基本操作示例
1. 创建数据库连接
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();
// 这里可以进行数据库操作
}
2. 查询操作
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($"ID: {person.Id}, Name: {person.Name}, Age: {person.Age}");
}
}
3. 插入操作
你还可以使用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($"Rows inserted: {affectedRows}");
}
4. 更新操作
更新数据库记录同样简单:
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($"Rows updated: {affectedRows}");
}
5. 删除操作
删除操作也非常直观:
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($"Rows deleted: {affectedRows}");
}
6. 多结果集查询
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($"Person: {person.Name}");
foreach (var order in orders)
{
Console.WriteLine($"Order ID: {order.OrderId}, Amount: {order.Amount}");
}
}
else
{
Console.WriteLine("No person found with the given ID.");
}
}
}
7. 存储过程
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($"Person: {person.Name}, Age: {person.Age}");
}
else
{
Console.WriteLine("No person found with the given ID.");
}
}
catch (SqlException ex)
{
Console.WriteLine($"SQL Error: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}
}
8. 事务支持
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($"Transaction rolled back: {ex.Message}");
}
}
}
9. 映射一对多关系
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($"Person: {result.Name}");
foreach (var order in result.Orders)
{
Console.WriteLine($"Order ID: {order.OrderId}, Amount: {order.Amount}");
}
}
10. 批量插入
虽然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($"Rows inserted: {affectedRows}");
}
这些例子展示了Dapper的强大和灵活性,使其能够应对从简单到复杂的各种数据库操作。无论是处理多结果集、事务、还是关系映射,Dapper都能提供高效的解决方案。
总结
Dapper在保持轻量级和性能优势的同时,提供了强大的数据库交互功能。对于需要高效进行数据库操作但并不适合全栈ORM(如Entity Framework)的项目,Dapper是一个理想的选择。此外,它与其他框架的兼容性,确保了开发者能够灵活地选择最佳的组合工具进行开发。
如果你从事上位机,自动化,机器视觉,IOT项目,数字化项目,欢迎加我微信,大家可以一起讨论学习,如果遇到技术问题可以提出来,我会尽量帮你解决问题,但不能保证喔,毕竟个人水平有限!