Dapper ORM

来源:互联网 发布:matlab图像分割算法 编辑:程序博客网 时间:2024/05/16 06:07

更新:2015/05/12:

SQL Server Dapper:http://www.codeproject.com/Articles/889668/SQL-Server-Dapper

  • Download demo project - 48.1 KB
  • Download SQLHelper.cs - 4.1 KB



<a target=_blank target="_blank" href="https://code.google.com/p/dapper-dot-net/">https://code.google.com/p/dapper-dot-net/</a>
https://code.google.com/p/dapper-dot-net/source/browse/Tests/Tests.cs


原文:http://www.renfb.com/blog/2011/Article/335

假如你喜欢原生的Sql语句,又喜欢ORM的简单,那你一定会喜欢上Dapper这款ROM.点击下载
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的连接数据库对象。SqlConnectionpublic 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("&nbsp;&nbsp;++++");        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 Id=@id";        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 name=@Name                          ,ModifiedOn=@ModifiedOn,Parentid=@Parentid where Id=@id";        return conn.Execute(query,cat);    }}

//删除一个类别:public int DeleteColumnCat(ColumnCat cat){    using (IDbConnection conn = OpenConnection())    {        const string query = "delete from ColumnCat where id=@id";        return conn.Execute(query, cat);    }}

下面介绍一下Dapper的高级用法

//Dapper对事务处理的例子,如删除类别的同时删除类别下的所有新闻。或者删除产品的同时,//删除产品图片表里关联的所有图片。public int DeleteColumnCatAndColumn(ColumnCat cat){    using (IDbConnection conn = OpenConnection())    {        const string deleteColumn = "delete from [Column] where ColumnCatid=@catid";        const string deleteColumnCat = "delete from ColumnCat where id=@Id";        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;    }}

0 0
原创粉丝点击