查看原文
科技

C# 中Dapper轻量级ORM 的应用详解

iamrick 技术老小子
2024-09-04

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 stringstring 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 INTASBEGIN 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 INTASBEGIN 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 pLEFT JOIN [Order] o ON p.Id = o.PersonIdWHERE 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项目,数字化项目,欢迎加我微信,大家可以一起讨论学习,如果遇到技术问题可以提出来,我会尽量帮你解决问题,但不能保证喔,毕竟个人水平有限!



个人观点,仅供参考
继续滑动看下一个
技术老小子
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存