为什么 80% 的码农都做不了架构师?>>> https://my.oschina.net/u/2663968/blog/3051541
假如你喜欢原生的 Sql 语句, 又喜欢 ORM 的简单, 那你一定会喜欢上 Dapper 这款 ROM. 点击下载 http://code.google.com/p/dapper-dot-net/
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 语法十分简单. 并且无须迁就数据库的设计.
下面介绍 Dapper 如何使用, 来进行高效开发, 以下操作是编译后在 Net3.5 下操作的例子, Net4.0 下大部分函数有默认值, 参数很简单.
- // 数据库里的表:
- CREATE TABLE ColumnCat
- (
- Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
- NAME NVARCHAR(150) NULL,
- ModifiedOn SMALLDATETIME NULL DEFAULT(GETDATE()),
- Parentid INT
- )
- CREATE TABLE Column
- (
- Id INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
- NAME NVARCHAR(150) NULL,
- ModifiedDate SMALLDATETIME NULL DEFAULT(GETDATE()),
- ColumnCatid INT null
- )
常用的表, 分类和内容表, 分类可以有下级类别. 以下操作基本上都是对这两个表的操作.
- // 连接数据库字符串.
- private readonly string sqlconnection =
- "Data Source=RENFB;Initial Catalog=test;User Id=sa;Password=sa;";
- //public readonly string mysqlconnectionString =
- @"server=127.0.0.1;database=test;uid=renfb;pwd=123456;charset='gbk'";
- // 获取 Sql Server 的连接数据库对象. SqlConnection
- public SqlConnection OpenConnection()
- {
- SqlConnection connection = new SqlConnection(sqlconnection);
- connection.Open();
- return connection;
- }
- // 获取 MySQL 的连接数据库对象. MySqlConnection
- //public MySqlConnection OpenConnection()
- //{
- // MySqlConnection connection = new MySqlConnection(mysqlconnectionString);
- // connection.Open();
- // return connection;
- //}
注: 如果需要换成 MySQL 数据库, 只用将获得 sql Server 的连接数据库对象的函数注释掉, 取消 MySQL 的连接数据库对象的函数的注释, 一并取消 MySQL 连接字符串的注释, 并修改为自己的连接信息.
Query()方法:
Query()是 IDbConnection 扩展方法并且重载了, 从数据库里提取信息, 并用来填充我们的业务对象模型.
- // 先创建一个类, 是数据库的 ColumnCat 表的模型.
- public class ColumnCat
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public DateTime ModifiedOn { get; set; }
- public int Parentid { get; set; }
- }
- // 获取 ColumnCat 对象的集合.
- public IEnumerable<ColumnCat> SelectColumnCats()
- {
- using (IDbConnection conn = OpenConnection())
- {
- const string query = "select * from ColumnCat order by id desc";
- return conn.Query<ColumnCat>(query,null);
- }
- }
就是这么简单, 直接在例子中嵌入 Sql, 很容易扩展为存储过程, 可以使用别名使结果集中的列与业务对象模型 (ColumnCat) 的属性对应.
- // 下面使用上面的集合显示出分类.
- List<ColumnCat> AllColumnCat =SelectColumnCats().ToList<ColumnCat>();
- foreach (ColumnCat cat in AllColumnCat.Where(c => c.Parentid == 0))
- {
- Response.Write("Name==>" + cat.Name + "\t");
- Response.Write("时间 ==>" + cat.ModifiedOn + "\t");
- Response.Write("<br/>");
- foreach (ColumnCat c in AllColumnCat
- .Where<ColumnCat>(subColumnCat => subColumnCat.Parentid == cat.Id))
- {
- Response.Write(" ++++");
- Response.Write("Name==>" + c.Name + "\t");
- Response.Write("时间 ==>" + c.ModifiedOn + "\t");
- Response.Write("<br/>");
- }
- }
- // 将一级类别和二级类别显示在页面上, 如果使用一个递归, 很容易实现无限级分类(你懂的).
- // 获取单个 ColumnCat 对象.
- public ColumnCat SelectColumnCat(int columnCatId)
- {
- using (IDbConnection conn = OpenConnection())
- {
- const string query = "select * from ColumnCat where [email protected]";
- return conn.Query<ColumnCat>(query, new { id=columnCatId})
- .SingleOrDefault<ColumnCat>();
- }
- }
这里我们传递了一个参数给 Query 方法, 参数可以是任何对象, 其属性在查询中与 sql 的参数匹配, 由于 Query 总是返回一个集合, 我们只需调用 SingleOrDefault 方法, 因为我们知道总是返回 0 或 1 行.
- //Dapper 也可以加载填充嵌套对象, 考虑这样一种情形, 考虑到新闻的类别属性, 返回类别对象,
- // 我们创建一个 Column 的类
- public class Column
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public DateTime ModifiedDate { get; set; }
- public ColumnCat ColumnCat { get; set; }
- }
- // 接下来我们来填充我们的业务对象.
- public IList<Column> SelectColumnsWithColumnCat()
- {
- using (IDbConnection conn = OpenConnection())
- {
- const string query = "select c.Id,c.Name,c.ModifiedDate,c.ColumnCatid
- ,cat.id,cat.[Name],cat.ModifiedOn,cat.Parentid from [Column] as c
- left outer join ColumnCat as cat on c.ColumnCatid=cat.id";
- return conn.Query<Column, ColumnCat, Column>(query
- , (column, columncat) => { column.ColumnCat = columncat; return column; }
- , null, null, false, "Id", null, null).ToList<Column>();
- }
- }
注: 1, 在填充嵌套对象的时候, 只好执行 ToList<>方法, 否则回报 ExecuteReader 要求已打开且可用的连接. 连接的当前状态为已关闭, 而单个对象不会报错, 估计是 using 结束后关闭了连接, 而嵌套对象在 map 的时候又执行了 ExecuteReader, 只好在 using 结束之前返回 list 集合.
2, 嵌套对象的参数是比较多的, 主要是前两个参数, 其它参数没用可以设 置为 null, 不过在 4.0 版本可以只写两个参数, 其它参数都有默认值. 特别要注意的是 splitOn, 这个参数不能为空, 否则会报对象为引用的错误. [splitOn 参数的意思是读取第二个对象的的分割列, 从哪个列起开始读取第二个对象, 如果表里的自增长列都为 Id, 可以设置这个参数为 "Id"] .
Execute 方法:
正如 Query 方法是检索数据的, Execute 方法不会检索数据, 它与 Query 方法非常相似, 但它总返回总数(受影响的行数), 而不是一个对象集合[如: insert update 和 delete] .
- // 接下来向数据库里添加一个类别
- public int InsertColumnCat(ColumnCat cat)
- {
- using (IDbConnection conn = OpenConnection())
- {
- const string query = "insert into ColumnCat([name],ModifiedOn,Parentid)
- values (@name,@ModifiedOn,@Parentid)";
- int row = conn.Execute(query,cat);
- // 更新对象的 Id 为数据库里新增的 Id, 假如增加之后不需要获得新增的对象,
- // 只需将对象添加到数据库里, 可以将下面的一行注释掉.
- SetIdentity(conn,id=>cat.Id=id,"id","ColumnCat");
- return row;
- }
- }
- public void SetIdentity(IDbConnection conn, Action<int> setId,string primarykey
- ,string tableName)
- {
- if (string.IsNullOrEmpty(primarykey)) primarykey = "id";
- if (string.IsNullOrEmpty(tableName))
- {
- throw new ArgumentException("tableName 参数不能为空, 为查询的表名");
- }
- string query = string.Format("SELECT max({0}) as Id FROM {1}", primarykey
- , tableName);
- NewId identity = conn.Query<NewId>(query, null).Single<NewId>();
- setId(identity.Id);
- }
- public class NewId
- {
- public int Id { get; set; }
- }
由于 Dapper 是通过类的属性自动绑定的, 所以增加了 NewId 类来获取增加对象后的 Id, 本来打算使用 @@identity,Net3.5 下使用总是 报错, 只好使用 Max 函数获取. 当然如果不需要获得更新后的对象的 ID, 可以不使用 SetIdentity, 这个函数通用.
- // 编译 Dapper 源码生成的是 Net4.0 下使用的, 可以借助 Net4.0 新增的 dynamic 动态类型,
- //SetIdentity 的实现将非常方便. 如下:
- public void SetIdentity<T>(IDbConnection conn, Action<int> setId)
- {
- dynamic identity = connection.Query("SELECT @@IDENTITY AS Id").Single();
- T newId = (T)identity.Id;
- setId(newId);
- }
- // 更新一个类别:
- public int UpdateColumnCat(ColumnCat cat)
- {
- using (IDbConnection conn = OpenConnection())
- {
- const string query = "update ColumnCat set [email protected]
- ,[email protected],[email protected] where [email protected]";
- return conn.Execute(query,cat);
- }
- }
- // 删除一个类别:
- public int DeleteColumnCat(ColumnCat cat)
- {
- using (IDbConnection conn = OpenConnection())
- {
- const string query = "delete from ColumnCat where [email protected]";
- return conn.Execute(query, cat);
- }
- }
下面介绍一下 Dapper 的高级用法
- //Dapper 对事务处理的例子, 如删除类别的同时删除类别下的所有新闻. 或者删除产品的同时,
- // 删除产品图片表里关联的所有图片.
- public int DeleteColumnCatAndColumn(ColumnCat cat)
- {
- using (IDbConnection conn = OpenConnection())
- {
- const string deleteColumn = "delete from [Column] where [email protected]";
- const string deleteColumnCat = "delete from ColumnCat where [email protected]";
- IDbTransaction transaction = conn.BeginTransaction();
- int row=conn.Execute(deleteColumn, new { catid =cat.Id},transaction,null,null);
- row += conn.Execute(deleteColumnCat, new { id=cat.Id},transaction,null,null);
- transaction.Commit();
- return row;
- }
- }
来源: http://www.bubuko.com/infodetail-3087040.html