C# Dapper
上次修改时间:2023 年 7 月 23 日
在本文中,我们将展示如何使用 Dapper 在 C# 中进行数据库编程。在示例中,我们使用 PostgreSQL。
Dapper
Dapper 是一个适用于 .NET 平台的简单对象映射器。它是一个将面向对象域模型映射到传统关系数据库的框架。
Dapper 的目标是代码简洁性和性能。
Dapper 没有特定于数据库的实现细节,它可以跨所有 .NET ADO 提供程序工作,包括 SQLite、SQL CE、Firebird、Oracle、MySQL、PostgreSQL 和 SQL Server。Dapper 由 Stack Overflow 团队创建。
$ dotnet add package Dapper
要使用 Dapper,我们使用 dotnet 工具将包引用添加到项目中。
$ dotnet add package Npgsql
我们还包括 PostgreSQL 的驱动程序。
CREATE TABLE cars(id serial PRIMARY KEY, name VARCHAR(255), price INT);
INSERT INTO cars(name, price) VALUES('Audi', 52642);
INSERT INTO cars(name, price) VALUES('Mercedes', 57127);
INSERT INTO cars(name, price) VALUES('Skoda', 9000);
INSERT INTO cars(name, price) VALUES('Volvo', 29000);
INSERT INTO cars(name, price) VALUES('Bentley', 350000);
INSERT INTO cars(name, price) VALUES('Citroen', 21000);
INSERT INTO cars(name, price) VALUES('Hummer', 41400);
INSERT INTO cars(name, price) VALUES('Volkswagen', 21600);
在我们的示例中,我们使用这个表。
C# Dapper ExecuteScalar
ExecuteScalar 方法执行一个查询,该查询选择单个值。
using Dapper;
using Npgsql;
string cs = @"User ID=postgres;Password=passwd;Host=localhost;Port=5432;Database=testdb";
using var con = new NpgsqlConnection(cs);
con.Open();
var ver = con.ExecuteScalar<string>("SELECT version()");
Console.WriteLine(ver);
该示例检索 PostgreSQL 数据库的版本。
string cs = @"User ID=postgres;Password=passwd;Host=localhost;Port=5432;Database=testdb";
我们提供 PostgreSQL 数据库的连接字符串。
using var con = new NpgsqlConnection(cs);
我们创建一个新的 NpgsqlConnection。
con.Open();
Open 方法打开与数据库的新连接。
var version = con.ExecuteScalar<string>("SELECT version()");
ExecuteScalar 方法执行 SELECT version() 查询,该查询返回单个值:PostgreSQL 的版本。
$ dotnet run PostgreSQL 11.1, compiled by Visual C++ build 1914, 64-bit
C# Dapper Query
Query 方法执行查询并将其映射到动态对象列表。
using Dapper;
using Npgsql;
string cs = @"User ID=postgres;Password=passwd;Host=localhost;Port=5432;Database=testdb";
using var con = new NpgsqlConnection(cs);
con.Open();
var cars = con.Query<Car>("SELECT * FROM cars").ToList();
cars.ForEach(car => Console.WriteLine(car));
record Car(int Id, string Name, int Price);
该示例检索 cars 表中的所有行。
var cars = con.Query<Car>("SELECT * FROM cars").ToList();
Query 方法执行 SELECT * FROM cars 语句并返回一个对象列表。
cars.ForEach(car => Console.WriteLine(car));
我们遍历列表并将所有元素打印到控制台。
$ dotnet run 1 Audi 52642 2 Mercedes 57127 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 6 Citroen 21000 7 Hummer 41400 8 Volkswagen 21600
C# Dapper ExecuteReader
ExecuteReader 执行 SQL 并返回一个 IDataReader。这通常在查询结果不由 Dapper 处理时使用,例如,用于填充 DataTable 或 DataSet。
using Dapper;
using Npgsql;
string cs = @"User ID=postgres;Password=passwd;Host=localhost;Port=5432;Database=testdb";
using var con = new NpgsqlConnection(cs);
con.Open();
var reader = con.ExecuteReader("SELECT * FROM cars");
while (reader.Read())
{
long id = reader.GetInt64(0);
string name = reader.GetString(1);
int price = reader.GetInt32(2);
Console.WriteLine($"{id} {name} {price}");
}
在该示例中,我们使用 ExecuteReader 从表中检索所有行。
while (reader.Read())
{
long id = reader.GetInt64(0);
string name = reader.GetString(1);
int price = reader.GetInt32(2);
Console.WriteLine($"{id} {name} {price}");
}
在这里,Dapper 没有进行映射。我们手动处理列。
$ dotnet run 1 Audi 52642 3 Skoda 9000 4 Volvo 29000 5 Bentley 350000 6 Citroen 21000 7 Hummer 41400 8 Volkswagen 21600 2 Mercedes 52000
C# Dapper Execute
Execute 方法执行一个 SQL 语句。它用于执行 INSERT、UPDATE 和 DELETE 语句。
using Dapper;
using Npgsql;
string cs = @"User ID=postgres;Password=passwd;Host=localhost;Port=5432;Database=testdb";
using var con = new NpgsqlConnection(cs);
con.Open();
int affectedRows = con.Execute("UPDATE cars SET price = 52000 WHERE id = 1");
Console.WriteLine($"UPDATE affected rows: {affectedRows}");
该示例更新单个汽车的价格并返回受影响的行数。
int affectedRows = con.Execute("UPDATE cars SET price = 52000 WHERE id = 1");
UPDATE 语句更新汽车的价格。Execute 方法返回更新的行数。
Console.WriteLine($"UPDATE affected rows: {affectedRows}");
更新的行数将打印到终端。
$ dotnet run UPDATE affected rows: 1
C# Dapper 参数化查询
参数化查询提高了安全性和性能。当我们编写参数化查询时,我们使用占位符而不是直接将值写入查询中。
using Dapper;
using Npgsql;
string cs = @"User ID=postgres;Password=passwd;Host=localhost;Port=5432;Database=testdb";
using var con = new NpgsqlConnection(cs);
con.Open();
var car = con.QueryFirst<Car>("SELECT * FROM cars WHERE id=@id",
new { id = 3 });
Console.WriteLine(car);
record Car(int Id, string Name, int Price);
该示例从表中选择一个特定的行。
var car = con.QueryFirst<Car>("SELECT * FROM cars WHERE id=@id",
new { id = 3 });
QueryFirst 返回 SQL 查询的第一个结果。@id 是一个要填充的占位符。第二个参数是填充占位符的参数。
$ dotnet run
Car { Id = 3, Name = Skoda, Price = 9000 }
下一个示例提供多个参数。
using Dapper;
using Npgsql;
string cs = @"User ID=postgres;Password=passwd;Host=localhost;Port=5432;Database=testdb";
using var con = new NpgsqlConnection(cs);
con.Open();
var cars = con.Query<Car>("SELECT * FROM cars WHERE id IN (@id1, @id2)",
new { id1 = 1, id2 = 2 });
Console.WriteLine(string.Join("\n", cars));
record Car(int Id, string Name, int Price);
我们查询两辆汽车。我们提供了一个带有给定 ID 的匿名对象。
$ dotnet run
Car { Id = 1, Name = Audi, Price = 52642 }
Car { Id = 2, Name = Mercedes, Price = 52000 }
C# Dapper 删除行
以下示例从表中删除一行。
using Dapper;
using Npgsql;
string cs = @"User ID=postgres;Password=passwd;Host=localhost;Port=5432;Database=testdb";
using var con = new NpgsqlConnection(cs);
con.Open();
int delRows = con.Execute(@"DELETE FROM cars WHERE Id = @Id", new { Id = 1 });
if (delRows > 0)
{
Console.WriteLine("car deleted");
}
该示例使用 Execute 方法删除一行。
C# Dapper QueryMultiple
QueryMultiple 方法执行一个返回多个结果集的命令,并依次返回每个结果集。
using Dapper;
using Npgsql;
string cs = @"User ID=postgres;Password=passwd;Host=localhost;Port=5432;Database=testdb";
using var con = new NpgsqlConnection(cs);
con.Open();
var sql = @"select * from cars where Id = @id1;
select * from cars where Id = @id2;
select * from cars where Id = @id3";
using var multi = con.QueryMultiple(sql, new { id1 = 1, id2 = 2, id3 = 3});
var c1 = multi.Read<Car>().Single();
var c2 = multi.Read<Car>().Single();
var c3 = multi.Read<Car>().Single();
Console.WriteLine(c1);
Console.WriteLine(c2);
Console.WriteLine(c3);
record Car(int Id, string Name, int Price);
该示例一次返回三个 SELECT 语句。
var sql = @"select * from cars where Id = @id1;
select * from cars where Id = @id2;
select * from cars where Id = @id3";
我们定义一个多重选择语句。每个语句都用分号分隔。
using var multi = con.QueryMultiple(sql, new { id1 = 1, id2 = 2, id3 = 3});
这些语句使用 QueryMultiple 执行。我们在 params 对象中提供 ID。
var c1 = multi.Read<Car>().Single(); var c2 = multi.Read<Car>().Single(); var c3 = multi.Read<Car>().Single();
我们使用 Read 读取 car 对象。
$ dotnet run
Car { Id = 1, Name = Audi, Price = 52642 }
Car { Id = 2, Name = Mercedes, Price = 57127 }
Car { Id = 3, Name = Skoda, Price = 9000 }
C# Dapper DynamicParameters
DynamicParameters 是一个参数包,可以传递给 Dapper 的 Query 和 Execute 方法。
using System.Data;
using Npgsql;
using Dapper;
string cs = @"User ID=postgres;Password=passwd;Host=localhost;Port=5432;Database=testdb";
using var con = new NpgsqlConnection(cs);
con.Open();
var query = "INSERT INTO cars(name, price) VALUES(@name, @price)";
var dp = new DynamicParameters();
dp.Add("@name", "Lada", DbType.AnsiString, ParameterDirection.Input, 255);
dp.Add("@price", 36600);
int res = con.Execute(query, dp);
if (res > 0)
{
Console.WriteLine("row inserted");
}
该示例将新行插入到 cars 表中。
var dp = new DynamicParameters();
dp.Add("@name", "Lada", DbType.AnsiString, ParameterDirection.Input, 255);
dp.Add("@price", 36600);
我们动态地提供参数值及其类型。
int res = con.Execute(query, dp);
动态参数作为 Execute 方法的第二个参数传递。
C# Dapper 批量插入
我们可以使用 Execute 插入多行。
using Dapper;
using Npgsql;
string cs = @"User ID=postgres;Password=passwd;Host=localhost;Port=5432;Database=testdb";
using var con = new NpgsqlConnection(cs);
con.Open();
var stm = "INSERT INTO cars(name, price) VALUES(@name, @price)";
var data = new List<Car>
{
new Car (Name: "Lada 2", Price : 63444 ),
new Car (Name: "Toyota 2", Price : 63330 )
};
int n = con.Execute(stm, data);
Console.WriteLine($"{n} cars inserted");
record Car(string Name, int Price);
该程序将两辆汽车插入到表中。
int n = con.Execute(stm, data);
Execute 方法将语句和对象列表作为参数。
来源
在本文中,我们展示了如何使用 Dapper 在 C# 中进行数据库编程。
作者
列出所有 C# 教程。