分享
 
 
 

参考资料

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: |||超大  

本文内容特点性能参数化的查询List 支持缓存和非缓存的 readers多个映射多个结果存储过程Ansi Strings 和 varchar限制和注意事项Dapper 能运行在我的 db 提供者上吗?有例子的完整例子列表吗?谁在使用 Dapper?参考跳槽了,新公司的数据库层,准确地说,数据库层和持久层使用 Dapper,这东西的确很方便~个人觉得这种方便性体现在三点:

能很方便地执行数据库 DML 和 DLL 操作。比如,当你执行一个带参数的 SQL 时,SQL 中的变量能与你传递给它的实体或匿名对象中的属性,自定匹配。而我们知道,带参数的 SQL,能提高数据库执行 SQL 的效率;能很方便地将数据库检索结果映射为面向对象的对象。从数据库中的检索结果,通常是张二维表,如 DataTable,而应用程序中是实体类,以及实体类的集合,那么 Dapper 能够将 DataTable 自动地映射成为实体类的集合;能很方便地书写 SQL 语句。比如,写多个 SQL,用分号分隔。下载 Demo(该下载包含 Dapper 项目,项目中有 Dapper 的测试示例和性能测试例子)(Dapper 的示例使用 SQLServer 数据库,我个人的示例是MySQL)特点Dapper 只有一个文件,你可以把它拖到你的项目中,来扩展你的IDbConnection接口。

它提供了三方面的帮助:

执行一个查询,并把结果映射到一个强类型 list注意:所有的扩展方法都假设数据库连接已打开,如果关闭连接,它们将失败。

publicstaticIEnumerable<T> Query<T>(thisIDbConnection cnn,stringsql,objectparam =null, SqlTransaction transaction =null,boolbuffered =true)

用法:

publicclassDog

{

publicint? Age { get; set; }

publicGuid Id { get; set; }

publicstringName { get; set; }

publicfloat? Weight { get; set; }

 

publicintIgnoredPRoperty { get {return1; } }

}

 

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);

执行一个查询,并把结果映射到一个动态 object 的 listpublicstaticIEnumerable<dynamic> Query (thisIDbConnection cnn,stringsql,objectparam =null, SqlTransaction transaction =null,boolbuffered =true)

该方法将执行 SQL,并返回一个动态 list,即var变量。

用法:

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);

rows[0]这种访问方式会出错,不知道示例是怎么给的~

执行一个不返回结果的 CommandpublicstaticintExecute(thisIDbConnection cnn,stringsql,objectparam =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);

多次执行一个 Command相同的签名也可以让你方便高效地对一个命令执行多次,例如批量加载数据(bulk-load data)。

用法:

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 rows inserted:"1,1","2,2"and"3,3"

对任何类型实现T为IEnumerable的参数都可以执行。

性能Dapper 的主要特点是性能。以下数据显示对一个数据库执行 SELECT 出 500 条,并把数据映射到对象中需要多长时间。

性能测试分为三个方面:

POCO 序列化框架,支持从数据库获得静态类型的对象。使用原始的 SQL。动态序列化框架,支持返回对象的动态列表。典型的框架用法。往往不会涉及编写 SQL。Performance of SELECT mapping over 500 iterations - POCO 序列化方法

持续时间(毫秒)

备注

Hand coded (using a SqlDataReader)

47

Can be faster

Dapper ExecuteMapperQuery

49

同上

ServiceStack.OrmLite (QueryById)

50

同上

PetaPoco 

52

同上

BLToolkit

80

同上

SubSonic CodingHorror

107

同上

NHibernate SQL

104

同上

Linq 2 SQL ExecuteQuery

181

同上

Entity framework ExecuteStoreQuery

631

同上

Performance of SELECT mapping over 500 iterations - dynamic 序列化方法

持续时间(毫秒)

备注

Dapper ExecuteMapperQuery (dynamic)

48

 

Massive

52

 

Simple.Data

95

 

Performance of SELECT mapping over 500 iterations - 典型用法方法

持续时间(毫秒)

备注

Linq 2 SQL CompiledQuery

81

Not super typical involves complex code

NHibernate HQL

118

 

Linq 2 SQL

559

 

Entity framework

859

 

SubSonic ActiveRecord.SingleOrDefault

3619

 

参数化的查询参数可以作为匿名类来传递。这使你可以轻松地给命名参数,只要简单地剪切和粘贴 SQL 片断,并在查询分析器中执行即可。

new{A = 1, B ="b"} // A will be mapped to the param @A, B to the param @B

List 支持Dapper 运行让你传递IEnumerable,自动地参数化的查询。

例如下面 SQL 的in查询:

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 =newint[] { 1, 2, 3 });

将被翻译为:

select * from (select 1asId union all select 2 union all select 3)asXwhereIdin(@Ids1, @Ids2, @Ids3)" // @Ids1 = 1 , @Ids2 = 2 , @Ids2 = 3

缓存和非缓存的 readersDapper 的默认动作是执行 SQL 并在返回时缓冲整个 reader。在大多数情况下,这是理想的,因为它能最大限度地减少数据库中的共享锁,以及减少数据库的网络时间。

但是,在执行庞大查询时,你可能为了减少内存的占用,只加载需要的对象。要做到这点,通过缓冲到查询方法中。

/// <summary>

/// NonBuffered

/// 将会抛出异常,Invalid attempt to Read when reader is closed.

/// </summary>

publicstaticvoidTestBasicStringUsageAsyncNonBuffered()

{

var query = DbHelp.QueryAsync<string>(newCommandDefinition("select 'abc' as Value union all select @txt",new{ txt ="def"}, flags: CommandFlags.None));

var arr = query.Result.ToArray();

arr.IsSequenceEqualTo(new[] {"abc","def"});

}

 

/// <summary>

/// Buffered

/// 不会抛出异常

/// </summary>

publicstaticvoidTestBasicStringUsageAsyncBuffered()

{

var query = DbHelp.QueryAsync<string>(newCommandDefinition("select 'abc' as Value union all select @txt",new{ txt ="def"}, flags: CommandFlags.Buffered));

var arr = query.Result.ToArray();

arr.IsSequenceEqualTo(new[] {"abc","def"});

}

/// <summary>

/// Pipelined

/// 将会抛出异常,Invalid attempt to Read when reader is closed.

/// </summary>

publicstaticvoidTestBasicStringUsageAsyncPipelined()

{

var query = DbHelp.QueryAsync<string>(newCommandDefinition("select 'abc' as Value union all select @txt",new{ txt ="def"}, flags: CommandFlags.Pipelined));

var arr = query.Result.ToArray();

arr.IsSequenceEqualTo(new[] {"abc","def"});

}

多个映射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;returnpost;});

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).First();}}}

如果你想要更灵活的操作,可以这样做:

var p =newDynamicParameters();

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);

 

intb = p.Get<int>("@b");

intc = p.Get<int>("@c");

Ansi Strings 和 varchar

Dapper 支持 varchar 参数,如果你在一个 varchar 列上执行一个 where 语句,确保下面方式传递参数:

Query<Thing>("select * from Thing where Name = @Name",new{Name =newDbString { Value ="abcde", IsFixedLength =true, Length = 10, IsAnsi =true});

在 SQL Server 上,当查询非 Unicode 时,查询 Unicode 和 ANSI 时需要使用 Unicode。

限制和注意事项对于 Dapper 执行的每个查询的缓存信息,使得它能够快速地物化对象和处理参数。当前的实现把信息缓存在一个 ConcurrentDictionary 对象中。它存储的对象永远不会被刷新。如果你生成的 SQL 字符串没有使用参数,那么可能会出现命中内存问题。我们把字典转换成 LRU(Least Recently Used)缓存。

ORM 的很多特点都被 Dapper 去掉了,没有身份地图(IdentityMap),没有更新/选择的助手等。

Dapper 不会管理你连接的生命周期,它假定它得到的连接是打开的,并且不存在 DataReader 枚举(除非启用 MARS)。

什么是 Mars?它是在创建数据库连接时指定的,下面是 Dapper 中连接 SQL Server 的示例:

publicstaticSqlConnection GetOpenConnection(boolmars =false)

{

var cs = connectionString;

if(mars)

{

SqlConnectionStringBuilder scsb =newSqlConnectionStringBuilder(cs);

scsb.MultipleActiveResultSets =true;

cs = scsb.ConnectionString;

}

var connection =newSqlConnection(cs);

connection.Open();

returnconnection;

}

如果指定了 Mars,那么还会创建SqlConnectionStringBuilder,并指定其MultipleActiveResultSets属性为true。不过,看 Dapper 的例子,貌似 SQL Server 是有 Mars 的,但 MySQL 没有。

Dapper 能运行在我的 db 提供者上吗?Dapper 能运行在所有 .net ado 提供者上,包括 sqlite,sqlce,firebird,Oracle,MySQL,PostgreSQL 和 SQL Server。

有例子的完整例子列表吗?Dapper 在测试项目中有完整的测试套件。

谁在使用 Dapper?目前使用 Dapper 的有 Stack Overflow 和 helpdesk。

(if you would like to be listed here let me know)

参考资料github Dapperstackoverflow DapperA Look at Dapper.NET 

下载 Demo

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有