Dapper2.0.78手册翻译
Dapper - .Net下的一个简单的ORM框架
特性
Dapper是一个NuGet库,你可以把它添加到你的项目中,扩展你的IDbConnection接口。
提供了3个方法
查询并映射一个实例集合
public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)
使用例子
public class Dog
{
public int? Age { get; set; }
public Guid Id { get; set; }
public string Name { get; set; }
public float? Weight { get; set; }
public int IgnoredProperty { get { return 1; } }
}
var guid = Guid.NewGuid();
var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
Assert.Equal(1,dog.Count());
Assert.Null(dog.First().Age);
Assert.Equal(guid, dog.First().Id);
查询并映射成dynamic集合
public static IEnumerable<dynamic> Query (this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)
使用例子
var rows = connection.Query("select 1 A, 2 B union all select 3, 4").AsList();
Assert.Equal(1, (int)rows[0].A);
Assert.Equal(2, (int)rows[0].B);
Assert.Equal(3, (int)rows[1].A);
Assert.Equal(4, (int)rows[1].B);
执行无返回结果的sql语句
public static int Execute(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)
使用例子
var count = connection.Execute(@"
set nocount on
create table #t(i int)
set nocount off
insert #t
select @a a union all select @b
set nocount on
drop table #t", new {a=1, b=2 });
Assert.Equal(2, count);
插入多个实例对象
var count = connection.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
);
Assert.Equal(3, count); // 3 rows inserted: "1,1", "2,2" and "3,3"
带参数查询
参数为一个匿名类
new {A = 1, B = "b"} // A will be mapped to the param @A, B to the param @B
Dapper允许你传入IEnumerable<int>,并将自动参数化你的查询。
connection.Query<int>("select * from (select 1 as Id union all select 2 union all select 3) as X where Id in @Ids", new { Ids = new int[] { 1, 2, 3 } });
相当于执行 select * from (select 1 as Id union all select 2 union all select 3) as X where Id in (@Ids1, @Ids2, @Ids3)" // @Ids1 = 1 , @Ids2 = 2 , @Ids2 = 3
类型转换
Dapper 支持bool和numeric的自动转换
connection.Query("select * from User where UserTypeId = {=Admin}", new { UserTypeId.Admin });
多实例映射
class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public User Owner { get; set; }
}
class User
{
public int Id { get; set; }
public string Name { get; set; }
}
var sql =
@"select * from #Posts p
left join #Users u on u.Id = p.OwnerId
Order by p.Id";
var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post;});
var post = data.First();
Assert.Equal("Sams Post1", post.Content);
Assert.Equal(1, post.Id);
Assert.Equal("Sam", post.Owner.Name);
Assert.Equal(99, post.Owner.Id);
假设做一个连接查询,将User对象放入Post对象更有意义。将user对象放入Post对象写法
(post, user) => { post.Owner = user; return post; }
Dapper可以通过假设Id列的名称为Id或Id来分割返回的行。如果主键不同,或者希望在Id以外的点分割行,可以使用可选的splitOn参数。
多结果查询
var sql =
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";
using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
var customer = multi.Read<Customer>().Single();
var orders = multi.Read<Order>().ToList();
var returns = multi.Read<Return>().ToList();
}
存储过程
一般写法
var user = cnn.Query<User>("spGetUser", new {Id = 1},
commandType: CommandType.StoredProcedure).SingleOrDefault();
第二种写法
var p = new DynamicParameters();
p.Add("@a", 11);
p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
cnn.Execute("spMagicProc", p, commandType: CommandType.StoredProcedure);
int b = p.Get<int>("@b");
int c = p.Get<int>("@c");
Ansi 字符串和varchar字符串
Dapper支持varchar参数,如果你在varchar列上使用一个参数执行where子句,请确保以这样的方式传递它:
Query<Thing>("select * from Thing where Name = @Name", new {Name = new DbString { Value = "abcde", IsFixedLength = true, Length = 10, IsAnsi = true });
在SQL Server上,查询unicode时使用unicode,查询非unicode时使用ANSI是至关重要的。
每行数据的类型切换
通常,您希望将给定表中的所有行视为相同的数据类型。但是,在某些情况下,能够将不同的行解析为不同的数据类型是很有用的。这是IDataReader的位置。GetRowParser可以派上用场。
假设您有一个名为“Shapes”的数据库表,列为:Id、Type和Data,您希望根据Type列的值将其行解析为Circle、Square或Triangle对象。
var shapes = new List<IShape>();
using (var reader = connection.ExecuteReader("select * from Shapes"))
{
// Generate a row parser for each type you expect.
// The generic type <IShape> is what the parser will return.
// The argument (typeof(*)) is the concrete type to parse.
var circleParser = reader.GetRowParser<IShape>(typeof(Circle));
var squareParser = reader.GetRowParser<IShape>(typeof(Square));
var triangleParser = reader.GetRowParser<IShape>(typeof(Triangle));
var typeColumnIndex = reader.GetOrdinal("Type");
while (reader.Read())
{
IShape shape;
var type = (ShapeType)reader.GetInt32(typeColumnIndex);
switch (type)
{
case ShapeType.Circle:
shape = circleParser(reader);
break;
case ShapeType.Square:
shape = squareParser(reader);
break;
case ShapeType.Triangle:
shape = triangleParser(reader);
break;
default:
throw new NotImplementedException();
}
shapes.Add(shape);
}
}
MySql中使用自定义变量
为 了在MySql中使用不带参数的sql,必须在连接字符串中使用Allow User Variables=True
限制与警告
Dapper会缓存运行查询结果,这允许它快速实体化对象和快速处理参数。当前实现将此信息缓存到ConcurrentDictionary对象中。只使用过一次的语句将定期从该缓存中刷新。但是,如果您在不使用参数的情况下动态生成SQL语句,则可能会遇到内存问题。
Dapper不包含数据库实现细节,它依赖于包括SQLite, SQL CE, Firebird, Oracle, MySQL, PostgreSQL和SQL Server的ADO.NET Provider。
Dapper只是简单的ORM框架,解决95%的应用问题,不试图解决所有问题
Dapper.Contrib - dapper的扩展
特性
Dapper.Contrib 包含插入、获取、更新和删除记录的方法。
以下是Dapper.Contrib包含的全部扩展方法清单:
T Get<T>(id); IEnumerable<T> GetAll<T>(); int Insert<T>(T obj); int Insert<T>(Enumerable<T> list); bool Update<T>(T obj); bool Update<T>(Enumerable<T> list); bool Delete<T>(T obj); bool Delete<T>(Enumerable<T> list); bool DeleteAll<T>();
如果实体模型存在Id属性,Dapper会默认Id属性为主键。
public class Car
{
public int Id { get; set; } // Works by convention
public string Name { get; set; }
}
如果实体模型不遵循包含Id属性,则必须在主键属性上加一个[Key] 或者 [ExplicitKey]特性。
public class User
{
[Key]
int TheId { get; set; }
string Name { get; set; }
int Age { get; set; }
}
[Key] 使用的时候,该属性必须是数据库主键并是自增。
[ExplicitKey] 只是在代码中作为主键,使用场景是数据库里面不是自增字段,在代码模型中作为主键使用。
Get 方法
根据Id获取实体数据
var car = connection.Get<Car>(1);
获取表中所有的实体数据
var cars = connection.GetAll<Car>();
Insert 方法
插入一个实体
connection.Insert(new Car { Name = "Volvo" });
插入多个实体
connection.Insert(cars);
更新一个实体
connection.Update(new Car() { Id = 1, Name = "Saab" });
更新多个实体
connection.Update(cars);
根据Id删除实体
connection.Delete(new Car() { Id = 1 });
删除多个实体
connection.Delete(cars);
删除全部实体
connection.DeleteAll<Car>();
其他特性
Dapper.Contrib 中的其他Atribute:
[Table("Tablename")] - 当表名和实体类名不一样,可使用该Atribute知名数据库中的表名
[Table ("emps")]
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
[Key] - 当数据库中没有自增Id的时候,使用Key这个Atribute来指明自增和主键字段
public class Employee
{
[Key]
public int EmployeeId { get; set; }
public string Name { get; set; }
}
[ExplicitKey] - 当数据库中没有自增字段,使用该Atribute来指明主键字段
public class Employee
{
[ExplicitKey]
public Guid EmployeeId { get; set; }
public string Name { get; set; }
}
-
[Write(true/false)]- 该Atribute来指明是否写数据库true为写,false为不写 -
[Computed]- 这个Atribute来指明不用更新数据库的字段限制与警告
-
SQLite
SQLiteConnection公开了一个与Dapper.Contrib提供的更新扩展冲突的更新事件。有两种方法可以解决这个问题。1、从SqlMapperExtensions显式调用Update方法-
SqlMapperExtensions.Update(_conn, new Employee { Id = 1, Name = "Mercedes" });2、使用一个类型参数来保证方法签名的唯一 -
connection.Update<Car>(new Car() { Id = 1, Name = "Maruti" });
本文来自博客园,作者:CelonY,转载请注明原文链接:https://www.cnblogs.com/CelonY/p/14220203.html
浙公网安备 33010602011771号