Dapper - a simple object mapper for .Net
特性
Dapper 是一个单独的文件,可以放进你的项目中用来扩展你的IDbConnection接口.
它提供了三个助手:
执行一个查询,并将结果映射到一个强类型集合中
注意:所有扩展方法假设连接已经打开,如果连接关闭,他们将会失败。
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 });
dog.Count()
.IsEqualTo(1);
dog.First().Age
.IsNull();
dog.First().Id
.IsEqualTo(guid);
执行一个查询,并将结果映射到一个动态类型集合中
该方法将执行SQL和返回一个动态集合。
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");
((int)rows[0].A)
.IsEqualTo(1);
((int)rows[0].B)
.IsEqualTo(2);
((int)rows[1].A)
.IsEqualTo(3);
((int)rows[1].B)
.IsEqualTo(4);
执行一个命令,不返回结果
public static int Execute(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)
使用例子:
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 })
.IsEqualTo(2);
多次执行一个命令
相同的占位符允许您方便有效的多次执行一个命令.
使用例子:
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 } }
).IsEqualTo(3); // 3 行 被插入: "1,1", "2,2" and "3,3"
性能
Dapper的一个关键特性是性能。以下指标显示对数据库执行500次SELECT语句并返回数据映射到对象,需要多长时间。
性能测试分为三个表格:
- POCO序列化框架支持从数据库到静态类型化对象,通过使用原始的SQL。
- 动态序列化框架支持返回动态对象的列表。
- 典型的框架使用。通常典型框架使用不同于最佳的使用性能明智。通常它不会涉及编写SQL。
500次查询映射的性能-POCO序列化
Method | Duration | Remarks |
---|---|---|
Hand coded (using a SqlDataReader ) | 47ms | Can be faster |
Dapper ExecuteMapperQuery | 49ms | |
ServiceStack.OrmLite (QueryById) | 50ms | |
PetaPoco | 52ms | |
BLToolkit | 80ms | |
SubSonic CodingHorror | 107ms | |
NHibernate SQL | 104ms | |
Linq 2 SQL ExecuteQuery | 181ms | |
Entity framework ExecuteStoreQuery | 631ms |
500次查询映射的性能-动态类型序列化
Method | Duration | Remarks |
---|---|---|
Dapper ExecuteMapperQuery (dynamic) | 48ms | |
Massive | 52ms | |
Simple.Data |
500次查询映射的性能-经典框架使用
Method | Duration | Remarks |
---|---|---|
Linq 2 SQL CompiledQuery | 81ms | Not super typical involves complex code |
NHibernate HQL | 118ms | |
Linq 2 SQL | 559ms | |
Entity framework | 859ms | |
SubSonic ActiveRecord.SingleOrDefault | 3619ms |
参数化查询
参数传递匿名类。这允许您命名参数容易和使您能够简单剪切和粘贴SQL代码片段在查询分析器和运行它们。
new {A = 1, B = "b"} // A 会被映射出参数 @A, B 对应 @B
集合参数的支持
Dapper允许您通过IEnumerable,自动化您的查询参数.
使用例子:
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的默认行为是执行sql和缓冲整个reader在返回。这是理想的在大多数情况下,因为它最大限度地减少共享锁在数据库和减少了数据库在网络上的时间。
然而当执行查询您可能需要减少内存占用并根据需要只加载对象。
多个映射
Dapper允许单个记录映射到多个对象。这是一个关键特性,如果你想避免无关的查询和渴望加载关联的对象。
使用例子:
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();
post.Content.IsEqualTo("Sams Post1");
post.Id.IsEqualTo(1);
post.Owner.Name.IsEqualTo("Sam");
post.Owner.Id.IsEqualTo(99);
重要注意Dapper假设您的Id列命名为“Id”或“Id”,如果你的主键不是,或你想分割宽行的“Id”,使用可选的“splitOn”参数。
多个结果
Dapper允许您处理多个结果在一个查询中.
例子:
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();
...
}
存储过程
Dapper完全支持存储过程
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 params,如果你是一个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和ansi当查询非unicode的时候。
限制和警告
Dapper缓存信息每个查询在它运行时,这使它迅速实现对象和工艺参数。当前的实现在ConcurrentDictionary最后对象缓存这些信息。它存储的对象不会被刷新。如果你是动态生成SQL字符串不使用参数有可能你将遇到内存问题。我们可以把词典转换为一个LRU缓存。
我能在我的数据库中使用吗?
Dapper没有DB具体的实现细节,它在所有工作。净ADO提供者includingSQLite、SQL CE、火鸟、Oracle、MySQL、PostgreSQL和SQL服务器。
转载于//www.cnblogs.com/szw1993/p/4776803.html
还没有评论,来说两句吧...