澳门新浦京娱乐场网站-www.146.net-新浦京娱乐场官网
做最好的网站

澳门新浦京娱乐场网站:Dapper简易教程,net平台

本文源自: 

本博客作者与Github上作者(cnxy)实为同一个作者。由于笔者翻译水平有限,文本中错误难免,欢迎指正!

 

特性


Dapper 是一个单独的文件,可以放进你的项目中用来扩展你的IDbConnection接口.

它提供了三个助手:

本文内容

  • 特点
  • 性能
  • 参数化的查询
  • List 支持
  • 缓存和非缓存的 readers
  • 多个映射
  • 多个结果
  • 存储过程
  • Ansi Strings 和 varchar
  • 限制和注意事项
  • Dapper 能运行在我的 db 提供者上吗?
  • 有例子的完整例子列表吗?
  • 谁在使用 Dapper?
  • 参考

跳槽了,新公司的数据库层,准确地说,数据库层和持久层使用 Dapper,这东西的确很方便~个人觉得这种方便性体现在三点:

  1. 能很方便地执行数据库 DML 和 DLL 操作。比如,当你执行一个带参数的 SQL 时,SQL 中的变量能与你传递给它的实体或匿名对象中的属性,自定匹配。而我们知道,带参数的 SQL,能提高数据库执行 SQL 的效率;
  2. 能很方便地将数据库检索结果映射为面向对象的对象。从数据库中的检索结果,通常是张二维表,如 DataTable,而应用程序中是实体类,以及实体类的集合,那么 Dapper 能够将 DataTable 自动地映射成为实体类的集合;
  3. 能很方便地书写 SQL 语句。比如,写多个 SQL,用分号分隔。

本文内容

  • 特点
  • 性能
  • 参数化的查询
  • List 支持
  • 缓存和非缓存的 readers
  • 多个映射
  • 多个结果
  • 存储过程
  • Ansi Strings 和 varchar
  • 限制和注意事项
  • Dapper 能运行在我的 db 提供者上吗?
  • 有例子的完整例子列表吗?
  • 谁在使用 Dapper?
  • 参考

跳槽了,新公司的数据库层,准确地说,数据库层和持久层使用 Dapper,这东西的确很方便~个人觉得这种方便性体现在三点:

  1. 能很方便地执行数据库 DML 和 DLL 操作。比如,当你执行一个带参数的 SQL 时,SQL 中的变量能与你传递给它的实体或匿名对象中的属性,自定匹配。而我们知道,带参数的 SQL,能提高数据库执行 SQL 的效率;
  2. 能很方便地将数据库检索结果映射为面向对象的对象。从数据库中的检索结果,通常是张二维表,如 DataTable,而应用程序中是实体类,以及实体类的集合,那么 Dapper 能够将 DataTable 自动地映射成为实体类的集合;
  3. 能很方便地书写 SQL 语句。比如,写多个 SQL,用分号分隔。

dapper只有一个代码文件,完全开源,你可以放在项目里的任何位置,来实现数据到对象的ORM操作,体积小速度快。 使用ORM的好处是增、删、改很快,不用自己写sql,因为这都是重复技术含量低的工作,还有就是程序中大量的从数据库中读数据然后创建model,并为model字段赋值。这些ORM都可以轻松给你搞定。ORM给我们开发带来便利时,性能也是一个让我们不得不考虑的问题。一般的ORM性能和直接写原生的sql比都差不少,但是Dapper性能还很错,甚至和DbHelperSQL方式性能高出很多。

本文翻译自:StackExchange.Dapper

执行一个查询,并将结果映射到一个强类型集合中


注意:所有扩展方法假设连接已经打开,如果连接关闭,他们将会失败。

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;

下载 Demo

下载 Demo

下载地址:

原版教程源自:Dapper Tutorial

执行一个查询,并将结果映射到一个动态类型集合中


该方法将执行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);

(该下载包含 Dapper 项目,项目中有 Dapper 的测试示例和性能测试例子)

(该下载包含 Dapper 项目,项目中有 Dapper 的测试示例和性能测试例子)

假如你喜欢原生的Sql语句,又喜欢ORM的简单,那你一定会喜欢上Dapper这款ROM。

中文教程源自:中文Dapper教程.GitBook

执行一个命令,不返回结果


public static int Execute(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)

使用例子:

connection.Execute(@"  set nocount on   create table #t   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);

(Dapper 的示例使用 SQLServer 数据库,我个人的示例是 MySQL)

(Dapper 的示例使用 SQLServer 数据库,我个人的示例是 MySQL)

 

中文教程PDF:dapper-tutorial-cn

多次执行一个命令


相同的占位符允许您方便有效的多次执行一个命令.

使用例子:

connection.Execute(@"insert MyTable(colA, colB) values ",    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 只有一个文件,你可以把它拖到你的项目中,来扩展你的 IDbConnection 接口。

它提供了三方面的帮助:

特点


Dapper 只有一个文件,你可以把它拖到你的项目中,来扩展你的 IDbConnection 接口。

它提供了三方面的帮助:

相关dapper实际项目源码下载:

Dapper - .Net版本的简单对象映射器

性能


Dapper的一个关键特性是性能。以下指标显示对数据库执行500次SELECT语句并返回数据映射到对象,需要多长时间。

性能测试分为三个表格:

  • POCO序列化框架支持从数据库到静态类型化对象,通过使用原始的SQL。
  • 动态序列化框架支持返回动态对象的列表。
  • 典型的框架使用。通常典型框架使用不同于最佳的使用性能明智。通常它不会涉及编写SQL。

执行一个查询,并把结果映射到一个强类型 list

注意:所有的扩展方法都假设数据库连接已打开,如果关闭连接,它们将失败。

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

执行一个查询,并把结果映射到一个强类型 list

注意:所有的扩展方法都假设数据库连接已打开,如果关闭连接,它们将失败。

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;

 

dog.First().Age

    .IsNull();

 

dog.First().Id

    .IsEqualTo;

基于ASP.NET MVC5和dapper的SEO关键词按天计费系统源码

发行说明

请见 stackexchange.github.io/Dapper

500次查询映射的性能-POCO序列化

Method

Duration

Remarks

Hand coded (using aSqlDataReader)

47ms

Can be faster

DapperExecuteMapperQuery

49ms

ServiceStack.OrmLite(QueryById)

50ms

PetaPoco

52ms

BLToolkit

80ms

SubSonic CodingHorror

107ms

NHibernate SQL

104ms

Linq 2 SQLExecuteQuery

181ms

Entity frameworkExecuteStoreQuery

631ms

执行一个查询,并把结果映射到一个动态 object 的 list

public static IEnumerable<dynamic> Query (this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = 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] 这种访问方式会出错,不知道示例是怎么给的~

执行一个查询,并把结果映射到一个动态 object 的 list

public static IEnumerable<dynamic> Query (this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)

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

用法:

var rows = connection.Query("select 1 A, 2 B union all select 3, 4");

 

((int)rows[0].A)

   .IsEqualTo;

 

((int)rows[0].B)

   .IsEqualTo;

 

((int)rows[1].A)

   .IsEqualTo;

 

((int)rows[1].B)

    .IsEqualTo;

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

dapper ASP.NET MVC5 sql文章&博客网站源码

组件

Nuget稳定版:

https://www.nuget.org/packages/Dapper

Visual Studio 程序包管理器控制台:

PM> Install-Package Dappe

特点

Dapper是一个NuGet库,您可以将其添加到项目中,以扩展您的IDbConnection接口。

它提供了3个使用方法:

500次查询映射的性能-动态类型序列化

Method

Duration

Remarks

DapperExecuteMapperQuery

48ms

Massive

52ms

Simple.Data

执行一个不返回结果的 Command

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

执行一个不返回结果的 Command

public static int Execute(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)

用法:

connection.Execute(@"

  set nocount on 

  create table #t 

  set nocount off 

  insert #t 

  select @a a union all select @b 

  set nocount on 

  drop table #t", new {a=1, b=2 })

   .IsEqualTo;

mvc5 dapper bootstrap2通用权限后台管理系统源码

执行一个查询并将结果映射到强类型列表

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

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

多次执行一个 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"

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

多次执行一个 Command


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

用法:

connection.Execute(@"insert MyTable(colA, colB) values ",

    new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }

  ).IsEqualTo; // 3 rows inserted: "1,1", "2,2" and "3,3"

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

 

执行一个查询并将其映射到动态对象列表

public static IEnumerable<dynamic> Query (this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)

这个方法会执行SQL语句,并返回一个动态列表。

示例:

var rows = connection.Query("select 1 A, 2 B union all select 3, 4");

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代码片段在查询分析器和运行它们。

new {A = 1, B = "b"} // A 会被映射出参数 @A, B 对应 @B 

性能


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

性能测试分为三个方面:

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

性能


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

性能测试分为三个方面:

  • POCO 序列化框架,支持从数据库获得静态类型的对象。使用原始的 SQL。
  • 动态序列化框架,支持返回对象的动态列表。
  • 典型的框架用法。往往不会涉及编写 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);

集合参数的支持


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

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

同上

Dapper的优势:

1,Dapper是一个轻型的ORM类。代码就一个SqlMapper.cs文件,编译后就40K的一个很小的Dll.
2,Dapper很快。Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。
3,Dapper支持什么数据库。Dapper支持Mysql,SqlLite,Mssql2000,Mssql2005,Oracle等一系列的数据库,当然如果你知道原理也可以让它支持Mongo db
4,Dapper的r支持多表并联的对象。支持一对多 多对多的关系。并且没侵入性,想用就用,不想用就不用。无XML无属性。代码以前怎么写现在还怎么写。
5,Dapper原理通过Emit反射IDataReader的序列队列,来快速的得到和产生对象。性能实在高高。
6,Dapper支持net2.0,3.0,3.5,4.0。【如果想在Net2.0下使用,可以去网上找一下Net2.0下如何配置运行Net3.5即可。】
7,Dapper语法十分简单。并且无须迁就数据库的设计。

多次执行命令

还允许使用相同的参数签名方便有效地多次执行命令(例如批量加载数据)

示例:

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行: "1,1", "2,2" 与 "3,3"

这适用于已经实现IEnumerable接口的集合对象T。

缓冲和无缓冲的读者


Dapper的默认行为是执行sql和缓冲整个reader在返回。这是理想的在大多数情况下,因为它最大限度地减少共享锁在数据库和减少了数据库在网络上的时间。

然而当执行查询您可能需要减少内存占用并根据需要只加载对象。

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

方法

持续时间(毫秒)

备注

Dapper ExecuteMapperQuery (dynamic)

48

 

Massive

52

 

Simple.Data

95

 

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

方法

持续时间

备注

Dapper ExecuteMapperQuery

48

 

Massive

52

 

Simple.Data

95

 

dapper的安装

在nuget里面搜索Dapper

澳门新浦京娱乐场网站 1

点击“安装”,会下载Dapper.dll,并把引用添加到项目中。

 

下面介绍Dapper如何使用,来进行高效开发,以下操作dapper是编译后在Net4.0下操作的例子。

性能

Dapper的一个关键特性是性能。 以下度量标准显示了对DB执行500个SELECT语句并将返回的数据映射到对象所需的时间。

性能测试分为3个列表:

  • 支持从数据库中提取静态类型对象框架的POCO序列化,使用原生SQL语句。
  • 支持返回动态对象列表框架的动态序列化。
  • 典型的框架用法:通常典型的框架使用与最佳使用性能明显不同,并且它不会涉及编写SQL语句。

多个映射


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”参数。

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

 

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

 

1、定义一个Person类对应数据库的Person表

CREATE TABLE [Person](
    [id] [int] IDENTITY(5,1) NOT NULL primary key nonclustered,
    [username] [nvarchar](100) NULL,
    [password] [nvarchar](100) NULL,
    [age] [int] NULL,
    [registerDate] [datetime] NULL,
    [address] [nvarchar](150) NULL
)

public class Person
{
        public int id { get; set; }
        public string username { get; set; }
        public string password { get; set; }
        public int age { get; set; }
        public DateTime registerDate { get; set; }
        public string address { set; get; }
}

超过500次迭代的SELECT映射性能 - POCO序列化

方法 执行时间 备注
手工编码 (使用 SqlDataReader) 47ms  
Dapper ExecuteMapperQuery 49ms  
ServiceStack.OrmLite (使用Id查询) 50ms  
PetaPoco 52ms 可以更快
BLToolkit 80ms  
SubSonic CodingHorror 107ms  
NHibernate SQL 104ms  
Linq 2 SQL ExecuteQuery 181ms  
Entity framework ExecuteStoreQuery 631ms  

多个结果


Dapper允许您处理多个结果在一个查询中.

例子:

var sql = @"select * from Customers where CustomerId = @idselect * from Orders where CustomerId = @idselect * 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();   ...} 

参数化的查询


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

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

参数化的查询


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

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

2、定义连接数据库字符串

public static string ConnString = "Server=.;Database=Test1;uid=sa;pwd=sa;";

超过500次迭代的SELECT映射性能 - 动态序列化

方法 执行时间 备注
Dapper ExecuteMapperQuery (动态) 48ms  
Massive 52ms  
Simple.Data 95ms  

存储过程


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

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 = 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

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 = 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

3、获取id大于2的所有Person,dapper返回类型是List类型

 public static List<Person> GetPersonList()
 {
        using (var conn = new System.Data.SqlClient.SqlConnection(ConnString))
        {
             conn.Open();
             var a = conn.Query<Person>("select * from Person where id>@id", new { id = 2 });
             conn.Close();
             return a.ToList();
        }
 }

这样返回的是List类型,可以充分利用linq的好处。

超过500次迭代的SELECT映射性能 - 典型用法

方法 执行时间 备注
Linq 2 SQL CompiledQuery 81ms 非典型的且不涉及复杂的代码
NHibernate HQL 118ms  
Linq 2 SQL 559ms  
Entity framework 859ms  
SubSonic ActiveRecord.SingleOrDefault 3619ms  

性能基准测试信息 点击这里.

可以任意提交包含其他ORM的补丁 - 运行基准测试时,请确保在Release中编译,且不能附加调试器 (Ctrl F5).

或者,你可以使用Frans Bouma的RawDataAccessBencher或OrmBenchmark测试套件作为测试工具使用。

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的时候。

缓存和非缓存的 readers


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

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

/// <summary>

/// NonBuffered

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

/// </summary>

public static void TestBasicStringUsageAsyncNonBuffered()

{

    var query = DbHelp.QueryAsync<string>(new CommandDefinition("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>

public static void TestBasicStringUsageAsyncBuffered()

{

    var query = DbHelp.QueryAsync<string>(new CommandDefinition("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>

public static void TestBasicStringUsageAsyncPipelined()

{

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

    var arr = query.Result.ToArray();

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

}

缓存和非缓存的 readers


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

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

/// <summary>

/// NonBuffered

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

/// </summary>

public static void TestBasicStringUsageAsyncNonBuffered()

{

    var query = DbHelp.QueryAsync<string>(new CommandDefinition("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>

public static void TestBasicStringUsageAsyncBuffered()

{

    var query = DbHelp.QueryAsync<string>(new CommandDefinition("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>

public static void TestBasicStringUsageAsyncPipelined()

{

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

    var arr = query.Result.ToArray();

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

}

4、dapper批量插入数据

public static void Execute()
{
    using (var conn = new SqlConnection(ConnString))
    {
        conn.Open();
        var r=conn.Execute(@"insert Person(username, password,age,registerDate,address) values (@a, @b,@c,@d,@e)",
        new [] { 
            new { a = 1, b = 1, c = 1, d = DateTime.Now, e = 1 }
            , new { a = 2, b = 2, c = 2, d = DateTime.Now, e = 2 }
            , new { a = 3, b = 3, c = 3, d = DateTime.Now, e = 3 } 
        }
                conn.Close();
         }
 );

执行上面方法会插入3条记录,这样sql可以灵活的控制,参数不用像ADO.Net那样声明每个参数,最后还要把参数集合赋值给ADO的命令。可以看出这样简洁多了。

澳门新浦京娱乐场网站 2

参数化查询

可以匿名类型作为参数进行传递,这可以轻松地命名这些参数名称,且能够在数据库平台的查询分析器中简单地使用剪切、粘贴SQL语句并运行。

new {A = 1, B = "b"} // A映射到参数@A,B映射到参数@B

限制和警告


Dapper缓存信息每个查询在它运行时,这使它迅速实现对象和工艺参数。当前的实现在ConcurrentDictionary最后对象缓存这些信息。它存储的对象不会被刷新。如果你是动态生成SQL字符串不使用参数有可能你将遇到内存问题。我们可以把词典转换为一个LRU缓存。

多个映射


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

post.Owner.Name.IsEqualTo("Sam");

post.Owner.Id.IsEqualTo;

提示:Dapper 假定你的 ID 列被命名为“ID”或“id”,如果你的主键是不同的,或者你想在点上拆分宽行点,而不是“ID”,可以使用可选的'splitOn'参数。

5、dapper修改数据,update

public static bool Update()
{
    using (var conn = new SqlConnection(ConnString))
    {
        conn.Open();
        var r = conn.Execute(@"update Person set password='www.lanhuseo.com' where username=@username", new { username = 2 });
        conn.Close();
        return r > 0;
    }
}

列表支持

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没有DB具体的实现细节,它在所有工作。净ADO提供者includingSQLite、SQL CE、火鸟、Oracle、MySQL、PostgreSQL和SQL服务器。

多个结果


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

   ...

} 

6、dapper删除数据

public static bool Delete()
{
    using (var conn = new SqlConnection(ConnString))
    {
        conn.Open();
        var r = conn.Execute(@"delete from Person where id=@id", new { id = 2 });
        conn.Close();
        return r > 0;
    }
}

文字代替

Dapper支持布尔与数字类型的文字代替。

connection.Query("select * from User where UserId = {=Id}", new {Id = 1}));

文字替换不作为参数发送; 更好的计划和过滤索引用法将被允许,但通常应谨慎在测试后使用。 当注入的值实际上是固定值(例如,特定于查询的“类别ID”,“状态代码”或“区域”)时,此功能特别有用。 当你在思考文字live数据时,也有可能想到also并测试特定于提供程序的查询提示,如带有常规参数的OPTIMIZE FOR UNKNOWN

存储过程


Dapper 完全支持存储过程:

var user = cnn.Query<User>("spGetUser", new {Id = 1}, 

        commandType: CommandType.StoredProcedure).First();}}}

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

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 Strings 和 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 和 ANSI 时需要使用 Unicode。

存储过程


Dapper 完全支持存储过程:

var user = cnn.Query<User>("spGetUser", new {Id = 1}, 

        commandType: CommandType.StoredProcedure).First();}}}

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

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 Strings 和 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 和 ANSI 时需要使用 Unicode。

7、dapper使用事务

using (var conn = new SqlConnection(ConnString))
{
    conn.Open();
    IDbTransaction trans = conn.BeginTransaction();
    int row = conn.Execute(@"update Person set password='www.lanhuseo.com' where id=@id", new { id = 3 }, trans, null, null);
    row  = conn.Execute("delete from Person where id=@id", new { id = 5 }, trans, null, null);
    trans.Commit();
}

缓冲与未缓冲阅读器

Dapper的默认行为是执行SQL并在返回时缓冲整个阅读器。 在大多数情况下,这是理想的,因为它最小化了数据库中的共享锁并减少了数据库网络时间。

但是,在执行大量查询时,可能需要最小化内存占用并仅根据需要加载对象。 为此,将buffered:false传递给Query方法。

限制和注意事项


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

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

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

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

public static SqlConnection GetOpenConnection(bool mars = false)

{

    var cs = connectionString;

    if (mars)

    {

        SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder(cs);

        scsb.MultipleActiveResultSets = true;

        cs = scsb.ConnectionString;

    }

    var connection = new SqlConnection(cs);

    connection.Open();

    return connection;

}

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

限制和注意事项


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

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

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

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

public static SqlConnection GetOpenConnection(bool mars = false)

{

    var cs = connectionString;

    if 

    {

        SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder;

        scsb.MultipleActiveResultSets = true;

        cs = scsb.ConnectionString;

    }

    var connection = new SqlConnection;

    connection.Open();

    return connection;

}

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

8、dapper集合批量插入

public static int InsertMultiple<T>(string sql, IEnumerable<T> entities, string connectionName = null) where T : class, new()
{
    using (SqlConnection cnn = GetOpenConnection(connectionName))
    {
        int records = 0;
        using (var trans = cnn.BeginTransaction())
        {
            try
            {
                cnn.Execute(sql, entities, trans, 30, CommandType.Text);
            }
            catch (DataException ex)
            {
                trans.Rollback();
                throw ex;
            }
            trans.Commit();
        }
        //foreach (T entity in entities)
        //{
        //    records  = cnn.Execute(sql, entity);
        //}
        return records;
    }
}

Dapper支持集合的插入,集合提交是一句直接的插入命令,所以速度会快很多。

通过上面的实例可以看到sql语句完全是我们自己控制,对于对EF和NHibernate这些自动给我们生成sql语句的这种机制不爽的同学就有福利了,我个人觉得这个Dapper和iBatis.Net机制都差不多,都是sql语句都是完全由程序员自己写,框架自身只负责数据转换成我们需要的Model相关的对象,这样程序性能得到了保证,但是也有一个不好的地方的所有的sql语句都要自己写,比如增、删、查、改,如果一个项目有上百个表,工作量也不小,还好有代码生成器把我们解放出来,例如:Codesmith。Dapper和iBatis.Net是大的区别是,Dapper更加简单和轻量,不用像iBatis.Net配置xml文件。

自从我认识了这个Dapper,项目如果性能要求比较好的情况下我就会首先Dapper,Dapper简单和轻量让我感觉相见恨晚。

多重映射

Dapper允许将单个行映射到多个对象。 如果想避免无关的查询和立即加载关联,这是一个很关键的特性。

例子:

思考这两个类: Post and User

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

现在我们要把posts表单与users表单进行映射查询。到目前为止,如果我们需要结合2个查询的结果,我们需要一个新的对象来表达它,但在这种情况下将User对象放在Post对象中更有意义。

这是多重映射的用户案例。你告诉dapper查询返回一个Post和一个User对象,然后给它描述你想要对包含PostUser对象的每一行做什么的函数。 在我们的例子中,我们想要获取用户对象并将其放在post对象中。所以编写函数如下:

(post, user) => { post.Owner = user; return post; }

Query方法的3个类型参数指定dapper应该使用哪些对象及返回的内容进行反序列化行。我们将把这两行解释为PostUser的组合,然后我们返回一个Post对象。 因此类型声明变为

<Post, User, Post>

所有东西都放在一起,看起来像这样:

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

Dapper能够通过假设Id列被命名为“Id”或“id”来拆分返回的行。 如果主键不同或者希望将行拆分为“Id”以外的其他位置,请使用可选的splitOn参数。

Dapper 能运行在我的 db 提供者上吗?


Dapper 能运行在所有 .net ado 提供者上,包括 sqlite,sqlce,firebird,oracle,MySQL,PostgreSQL 和 SQL Server。

Dapper 能运行在我的 db 提供者上吗?


Dapper 能运行在所有 .net ado 提供者上,包括 sqlite,sqlce,firebird,oracle,MySQL,PostgreSQL 和 SQL Server。

多重结果

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 在测试项目中有完整的测试套件。

有例子的完整例子列表吗?


Dapper 在测试项目中有完整的测试套件。

存储过程

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

谁在使用 Dapper?


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

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

谁在使用 Dapper?


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

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

澳门新浦京娱乐场网站:Dapper简易教程,net平台性能很不错的轻型ORM类Dapper。Ansi字符串和varchar

Dapper支持varchar参数,如果使用param在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编码时,变得至关重要。

参考资料


  • github Dapper
  • stackoverflow Dapper
  • 澳门新浦京娱乐场网站:Dapper简易教程,net平台性能很不错的轻型ORM类Dapper。A Look at Dapper.NET

 

下载 Demo

参考资料


  • github Dapper
  • stackoverflow Dapper
  • A Look at Dapper.NET

 

下载 Demo

每行类型转换

通常,自己希望将给定表中的所有行视为相同的数据类型。 但是,在某些情况下,能够将不同的行解析为不同的数据类型是有用的。 这就是IDataReader.GetRowParser派上用场的地方。

假设有一个名为“Shapes”的数据库表,其中包含列:IdTypeData,你想要基于Type列的值将它的行解析为CircleSquareTriangle对象。

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

限制与警告

Dapper缓存有关它运行的每个查询的信息,这使它能够快速实现对象并快速处理参数。 当前实现将此信息缓存在ConcurrentDictionary对象中。仅使用一次的语句通常会从此缓存中刷新。尽管如此,如果您在不使用参数的情况下动态生成SQL字符串,则可能会遇到内存问题。

Dapper的简洁性意味着ORM附带的许多功能都被剥离了。Dapper担心95%的情况,并为您提供大多数时间所需的工具,并不试图解决所有问题。

Dapper支持哪些数据库?

Dapper没有特定于DB的实现细节,它适用于所有.NET ADO提供程序,包括SQLite(https://www.sqlite.org/),SQL),SQL CE,Firebird,Oracle,MySQL,PostgreSQL和SQL Server。

有完整的例子清单吗?

Dapper有一个完整位于测试工程的测试套件。

谁在用这个?

Stack Overflow正在使用Dapper。

本文由澳门新浦京娱乐场网站发布于www.146.net,转载请注明出处:澳门新浦京娱乐场网站:Dapper简易教程,net平台