在开发带数据库的.NET系统中我使用过各种方式,包括直接使用ADO.NET、使用基于ADO.NET封装的各类工具(其中有自己封装的)、还有各类ORM类库,比如NHibernate、MyBatisNet、Linq to SQL、Entity Framwrok等,在上面的工具或类库中,MyBatisNet一段时间曾是我的最爱:由于它基于XML的配置可以灵活适应一些特殊的场景,不过有时候在面对中小型项目时又觉得MyBatisNet有些大材小用,此外还有一个原因是MyBatisNet这个基于Java的MyBatis改造而来的项目最近几乎没有更新了。 很早就听说过Dapper这个类库了,只不过一直没有尝试使用,但是很早就知道它是国外大型IT问答社区StackOverFlow最早开发并开源的。最近用了一下,感觉确实很方便。Dapper的源代码放在github上托管,并且可以用NuGet方式添加到项目中,只不过我现在开发的桌面软件有一部分用户还在使用WindowsXP系统,因此不能使用高于.NET Framrwork4.5以上版本开发且开发工具是Visual Studio 2015,这也限制了我不能使用最新版本的Dapper,于是我选择了Dapper 1.50.2这个版本。 我们可以在Visual Studio 2015中直接使用NuGet来添加,具体办法就是“工具”-“NuGet包管理器”-“管理解决方案的BuGet程序包”,如下图所示: ![](https://s4.51cto.com/images/blog/201805/08/ceb87c353b685b3197ed0d08dffeeb78.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=) 然后在弹出的窗口中搜索“Dapper”,如下图所示: ![](https://s4.51cto.com/images/blog/201805/08/263438992aa7644b0cf1448f261fc249.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=) 在上述界面中可以选择安装到当前解决方案的那些项目中,并且还可以指定Dapper的版本。 本文的描述都是针对Dapper 1.50.2版本。 **扩展方法介绍** 在介绍Dapper之前首先要介绍一下.NE中的扩展方法。扩展方法是.NET3.5添加的一个特性,使用扩展方法可以让你为现有的类扩展方法而无需创建新的派生类。下面以一个例子来说明: 在我解析某个XML文件节点时,需要读取某个节点的属性,但是这个节点并不是一直有这个属性值,如下: 为了避免name属性不存在时抛出异常,我必须先进行判断,如下: ``` string name=string.Empty; if (subNetworkNode.Attributes["name"] != null) { name=subNetworkNode.Attributes["name"].Value; } ``` 如果一个XML节点里有几个可能不存在的属性时,就需要处处这样判断了,于是我对代码进行了改进,针对此类情况定义了扩展方法,方法如下: ``` public static class ExtendMethodClass { /// /// 获取指定属性的值,如果没有设置指定属性名,则返回空字符串 /// /// XML节点的属性集合 /// 属性名 /// public static string GetAttributeValue(this XmlAttributeCollection attributes,string attributeName) { if (string.IsNullOrEmpty(attributeName)) { throw new ArgumentNullException("attributeName", "不能为空"); } if (attributes == null||attributes[attributeName]==null) { return string.Empty; } return attributes[attributeName].Value; } } ``` 这样一来,原来的代码就可以写成如下了: ``` string name = subNetworkNode.Attributes.GetAttributeValue("name"); ``` 初一看,就像是XmlAttributeCollection这类原来就有GetAttributeValue(string attributeName)这样一个方法,其实这个方式是我们自己扩展的。 定义扩展方法有几点: 1、定义扩展方法的类必须用static修饰,即必须为静态类。 2、定义的扩展方法必须用static修饰,即必须为静态方法,同时方法的第一个参数前必须加this修饰,this后必须是类名,表示为this后的类添加扩展方法,如本例中this XmlAttributeCollection attributes表示为XmlAttributeCollection这个类添加扩展方法,如果需要在方法体内访问XmlAttributeCollection这个类的实例,通过后面的attributes参数即可(注意这个参数的名称可以随便取)。 **Dapper介绍** 通过上面的介绍,大家可以初步了解扩展方法是怎么回事。其实Dapper主要也是用了扩展方法为IDbConnection和IDataReader添加扩展方法,比如在SqlMapper.cs中有如下代码为IDbConnection添加扩展方法(节选): ``` // /// Execute parameterized SQL. /// /// The connection to query on. /// The SQL to execute for this query. /// The parameters to use for this query. /// The transaction to use for this query. /// Number of seconds before command execution timeout. /// Is it a stored proc or a batch? /// The number of rows affected. public static int Execute(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) { var command = new CommandDefinition(sql, param, transaction, commandTimeout, commandType, CommandFlags.Buffered); return ExecuteImpl(cnn, ref command); } /// /// Execute parameterized SQL. /// /// The connection to execute on. /// The command to execute on this connection. /// The number of rows affected. public static int Execute(this IDbConnection cnn, CommandDefinition command) => ExecuteImpl(cnn, ref command); ``` 在SqlMapper.IDataReader.cs为IDataReader添加扩展方法的代码(节选): ``` /// /// Parses a data reader to a sequence of data of the supplied type. Used for deserializing a reader without a connection, etc. /// /// The type to parse from the . /// The data reader to parse results from. public static IEnumerable Parse(this IDataReader reader) { if (reader.Read()) { var deser = GetDeserializer(typeof(T), reader, 0, -1, false); do { yield return (T)deser(reader); } while (reader.Read()); } } /// /// Parses a data reader to a sequence of data of the supplied type (as object). Used for deserializing a reader without a connection, etc. /// /// The data reader to parse results from. /// The type to parse from the . public static IEnumerable Parse(this IDataReader reader, Type type) { if (reader.Read()) { var deser = GetDeserializer(type, reader, 0, -1, false); do { yield return deser(reader); } while (reader.Read()); } } ``` 在本人2011年7月25日写的一篇名为《利用ADO.NET的体系架构打造通用的数据库访问通用类》的博客当中介绍了ADO.NET的体系架构,如下图: ![](https://s4.51cto.com/images/blog/201805/08/20a6bd9113c93f2b3eabd32eed5887ad.jpg?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=) 就是首先定义了一系列的借口,如IDbConnection之类的,任何基于数据库访问只要实现了接口的定义,就都能在.NET访问,包括了微软自己对SQL Server和Access等数据库的实现以及MySQL和Oracle针对这个定义的第三方实现(其实JDBC也是这个道理,只不过是基于Java实现罢了)。因为包括SQL Server/MySQL/Oracle/PostgreSQL/SQLite在内的数据库都实现了IDbConnection的定义,而Dapper又是基于IDbConnection的扩展,因此使用Dapper理论上可以访问任何支持ADO.NET访问的数据库(前提是需要相关的数据库驱动,dll形式)。 在使用Dapper的实际开发中,用得较多的还是针对IDbConnection的扩展方法,主要有: int Execute():相当于Command.ExecuteNonQuery(),指定增加、删除、修改SQL语句,返回受影响的行数。 object ExecuteScalar():相当于Command. ExecuteScalar(),返回结果集第一行第一列,用于聚合函数等。 T ExecuteScalar():相当于Command. ExecuteScalar(),返回结果集第一行第一列,不过返回的结果指定了具体类型。 IDataReader ExecuteReader():相当于Command. ExecuteReader()。 IEnumerable Query() IEnumerable Query() IEnumerable Query() IEnumerable Query() dynamic QueryFirst() dynamic QueryFirstOrDefault() dynamic QuerySingle() dynamic QuerySingleOrDefault() IEnumerable Query() T QueryFirst() T QueryFirstOrDefault() T QuerySingle() T QuerySingleOrDefault() IEnumerable Query() object QueryFirst() object QueryFirstOrDefault() object QuerySingle() object QuerySingleOrDefault() 对于上面各种类型的Query和返回结果,就是分几种情况:返回一个实现IEnumerable接口的结果集,返回单个结果,返回单个结果或在没有找到匹配结果下返回默认值(引用类型、数值类型、枚举、日期等的默认值) **基本用法** 使用了Dapper之后,在插入或者查询时默认是按照数据库字段名与类属性名不区分大小写的情况下对应。 加入有在SQL Server中有如下表: ``` CREATE TABLE IF NOT EXISTS tblBay ( Id integer NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, Name nvarchar(50) not null, Desc nvarchar(100) not null ) ``` 同时有如下类定义: ``` public class Bay { public int ID { get; set; } public string Name { get; set; } public string Desc { get; set; } } ``` 那么插入可以这么写: ``` string connectionString = ".";//将这里改成你自己的数据库连接字符串 string sqlInsert = "INSERT INTO tblBay(Name,Desc)VALUES(@Name,@Desc)"; SqlConnection connection = new SqlConnection(connectionString); Bay bay = new Bay { Name = "test", Desc = "desc" }; connection.Execute(sqlInsert, bay); ``` 查询可以这么写: ``` string connectionString = ".";//将这里改成你自己的数据库连接字符串 string sqlQuery = "select * from tblBay where Id=@Id"; int id = 1; SqlConnection connection = new SqlConnection(connectionString); IEnumerable bayList = connection. QueryFirstOrDefault(sqlQuery,new { @Id = id }); ``` `字段与属性不一致情况下关联` 但是在某些情况下,比如使用MySQL数据库时我们可能会在由多个单词构成的字段名之间以下划线分割,如”user_id”、”user_name”等,而定义实体类时我们又将实体类的属性定义为UserId、UserName,那么就需要为他们之间建立关联,比较简单的一种方式就是在select的时候使用as。 假定在MySQL中存在如下表: ``` CREATE TABLE IF NOT EXISTS tblperson ( user_id integer NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, user_name nvarchar(50) not null, email nvarchar(100) not null ) ``` 而对应的实体类为: ``` public class Person { public int UserId { get; set; } public string UserName { get; set; } public string Email { get; set; } } ``` 那么插入可以这么写: ``` string connectionString = ".";//将这里改成你自己的数据库连接字符串 string sqlInsert = "INSERT INTO tblperson(user_name,email)VALUES(@Name,@Email)"; SqlConnection connection = new SqlConnection(connectionString); Person person = new Person { UserName = "test", Email = "email@email.com" }; DynamicParameters parameters = = new DynamicParameters(); parameters.Add("@Name", person.UserName); parameters.Add("@Email", person.Email); connection.Execute(sqlInsert, parameters); ``` 查询可以这么写: ``` string connectionString = ".";//将这里改成你自己的数据库连接字符串 string sqlQuery = "select user_id as userId,user_name as username,email from tblperson where user_id=@UserId"; int userId = 1; SqlConnection connection = new SqlConnection(connectionString); DynamicParameters parameters = = new DynamicParameters(); parameters.Add("@UserId ", userId); IEnumerable bayList = connection. QueryFirstOrDefault(sqlQuery, parameters); ``` 也就是数据库字段名与实体类属性名如果忽略大小写的情况下是一致的,则我们无需单独处理它们之间的映射关系,如果数据库字段名与实体类属性在忽略大小写的情况下仍然不一致,那么我们需要手动处理映射:在INSERT、DELETE、UPDATE时可以通过DynamicParameters来处理;在SELECT时可以通过在SQL语句中使用AS来处理。 有关Dapper的更进一步用法可以查看Dapper的用户手册或直接查看源代码。 周金桥 2018/04/22
提问和评论都可以,用心的回复会被更多人看到 评论
发布评论
全部评论 (1)

下一行code_ 回复了

2019-07-30 01:02

非常感谢1
回复 点赞 删除

相关文章

  • 数据库方面的面试题

    1.存储过程和函数的区别 2.事务是什么? 3.游标的作用?如何知道游标已经到了最后? 4.触发器分为事前触发和事后触发,这两种触发有和区别。语句级触发和行级触发有何区别。...

  • asp.net core中使用Dapper进行数据库管理

    准备工作一个接口一个(数据库管理)    public interface DBInterface    &

  • 数据库方面的一些问题

    一.数据库 1.如何设计一个关系型数据库数据库的各个模块: 存储(文件系统): 将数据持久化到硬盘。

  • 封装数据库访问

    开发伊始就想试一试封装数据库访问。   前言: 1。开发工具 Myeclipse。 2。数据库 Oracle 10g ,MSSQL2005 3。

  • C#.net数据库访问及其操作

    using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Data;using System.Data.SqlClient;using System.Configuration;using System.Text;using System.Text.RegularExp...

  • 【.NET 框架】—— Dapper框架基于Sqlserver数据库CRUD操作(一)

       【.NET 框架】—— Dapper框架基于Sqlserver数据库CRUD操作(一)     1.Dapper框架介绍Dapper是.NET开发中一款轻量级的ORM映射框架,

  • 【.NET 框架】—— Dapper框架基于Sqlserver数据库CRUD操作(一)

    1.Dapper框架介绍Dapper是.NET开发中一款轻量级的ORM映射框架,它轻量级、速度快,与同类型ORM框架如EF框架相比具有更高的执行效率。

  • .net+msmq快速访问数据库

    msmq是微软消息队列的英文缩写。那么什么是消息队列?消息队列是 Windows 2000(nt也有msmq,win95/98/me/xp不含消息队列服务但是支持客户端的运行)操作系统中通讯的基础,也是用于创建分布式、松散连接通讯...

  • 使用ADO.NET访问数据库

    一、ADO.NET:数据库访问的方法和技术。

  • ADO.net 数据库操作

    using System; using System.Data; using System.Data.SqlClient; using System.Configuration; using System.Web; using System.Web.Configuration; using System.Web.Security; using System.Web.UI; using Syste...

  • 数据库介绍

        数据库是“按照数据结构来组织、存储和管理数据的仓库”。

  • 数据库介绍

    什么是数据库数据库(Database)顾名思义,就是存入数据的仓库。准确的说是按照数据结构来组织、存储和管理数据的仓库。

  • 数据库介绍

    数据库技术概述数据(Data)早期计算机系统主要用于科学计算,数据主要指数值型数据现代的计算机系统数据是广义的,包括数字、文字、视频、音频等语义:一个数据可以代表不同的属性数据库(Database,DB

  • 数据库介绍

    数据库介绍 1.1 什么是数据库 顾名思义: 数据库就是存储数据的仓库.

  • oracle数据库下使用iSQL*Plus DBA访问数据库

    实验目的:iSQL*Plus DBA访问数据库 环境:oracle 10g 实验步骤: 一、启动iSQL*Plus服务:isqlplusctl start 二、浏览器地址栏中输入:http:/

  • .NetCore(C#)中使用ODP.NET Core+Dapper操作Oracle数据库

    前言Oracle 关系数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的 适应高吞吐量的数据库解决方案。

  • 数据库访问技术(二)---ADO.NET

    ADO.NET的名称起源于ADO(ActiveX Data Objects),是一个COM组件***,用于以往的Microsoft技术中访问数据

  • PHP 中CodeIgniter的数据库访问

     好吧,因为组织需要,最近又开始转战php了,业务逻辑都还好说,主要是老大要求在数据访问层上加上登录态验证。 其实这种要求也是合理的,互联网服务要求上层保护下层,但下层不能完全相信上层。

  • 抽离CodeIgniter的数据库访问

    点击查看原文章 好吧,因为组织需要,最近又开始转战php了,业务逻辑都还好说,主要是老大要求在数据访问层上加上登录态验证。

  • 鸿蒙官方战略合作共建——HarmonyOS技术社区

    HarmonyOS(鸿蒙)技术社区是由51CTO和华为共同打造的综合性开发和应用技术社区。作为华为的官方战略合作伙伴,51CTO将多年的社区运营经验与华为的技术赋能相结合,为开发者提供高质量有深度的HarmonyOS(鸿蒙)学习交流平台。

推荐专栏 更多