一,介绍:Dapper是一款轻量级ORM工具。如果你在小的项目中,使用Entity Framework、NHibernate 来处理大数据访问及关系映射,未免有点杀鸡用牛刀。你又觉得ORM省时省力,这时Dapper 将是你不二的选择。

  ---ORM框架的核心思想是对象关系映射,ORM是将表与表之间的操作,映射成对象和对象之间的操作,就是通过操作实体类来达到操作表的目的。从数据库提取的数据会自动按你设置的映射要求封装成特定的对象。之后你就可以通过对对象进行操作来修改数据库中的数据。这时候你面对的不是信息的碎片,而是一个形象鲜明的对象。

二,假如你喜欢原生的Sql语句,又喜欢ORM的简单,那你一定会喜欢上Dapper,这款ROMDapper的优势:

  1. 轻量。只有一个文件(SqlMapper.cs),编译完成之后只有120k(好象是变胖了)
  2. 速度快。Dapper的速度接近与IDataReader,取列表的数据超过了DataTable。
  3. 支持多种数据库。Dapper可以在所有Ado.net Providers下工作,包括sqlite, sqlce, firebird, oracle, MySQL, PostgreSQL and SQL Server
  4. 可以映射一对一,一对多,多对多等多种关系。
  5. 性能高。通过Emit反射IDataReader的序列队列,来快速的得到和产生对象,性能不错。
  6. 支持FrameWork2.0,3.0,3.5,4.0,4.5  

下面介绍Dapper如何使用,来进行高效开发,以下操作是编译后在Net3.5下操作的例子,Net4.0下大部分函数有默认值,参数很简单。

三, 为什么要扩展Dapper?

  了解Dapper都知道,在书写代码时,我们还是会手动写SQL,扩展的目的就是在完全不改变dapper源代码和使用基础上,进行一次封闭,达到零SQL,实现完全对象操作。

四,原生Dapper使用流程:

  0,两种下载使用方法:

  (1),推荐下载方法(使用Nuget下载):

  ---Nuget是一个.NET平台下的开源的项目,它是Visual Studio的扩展。在使用Visual Studio开发基于.NET Framework的应用时,Nuget能把在项目中添加、移除和更新引用的工作变得更加快捷方便。

  

  ---安装成功以后,生成一下网站,项目bin目录下,会生成几个Dapper文件(主要是Dapper.dll,120k)。

  (2),可以在官网上下载Dapper源代码,即SqlMapper.cs文件,在项目中App_Code文件夹中加入这个文件,就像Ado.net中的SqlHelper一样。

  ---源文件地址:https://github.com/StackExchange/dapper-dot-net/blob/master/Dapper%20NET40/SqlMapper.cs

  1,下面可以在项目中开始使用Dapper了

  2,连接数据库字符串。根据不同的数据库进行相应设置,如果是SQL,就类似下边设置;如果是使用SQLite,则设置方法不同。

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

  3,获取Sql Server的连接数据库对象。

public SqlConnection OpenConnection()
{
    SqlConnection connection = new SqlConnection(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扩展方法并且重载了,从数据库里提取信息,并用来填充我们的业务对象模型。

  4,//先创建一个类,是数据库的user表的模型。
  public class user
     {
        public int id { get; set; }
        public string name { get; set; }
        public string address { get; set; }
        public string age { get; set; }
     }
    5,手写Sql插入数据(增)

    /// <summary>
        /// 手写Sql插入数据
        /// </summary>
        public int InsertWithSql()
        {
            using (var conn = SQLiteHelper.OpenConnection())  //这里访问的是Sqlite数据文件,这里OpenConnection即上边获取连接数据库对象方法
            {
                user user=new user();
                user.name = "Dapper01";
                user.address = "周口";
                user.age="15";
                //string _sql = "INSERT INTO User(name,address,age)VALUES('Dapper01','周口',13)";
                string _sql = "INSERT INTO User(name,address,age)VALUES(@name,@address,@age)";
                return conn.Execute(_sql,user);
            }
        }

    ---如果不用Dapper,用插入一条数据需要多少代码量(相对上边只用了2行代码,下边需要用6行代码):

   public static int insert_news(string title, string content)
    {
        string sql = "insert into news(title,content,addtime) values(@title,@content,@addtime)";
        SQLiteParameter[] parameters =
            {
                SQLiteHelper.MakeSQLiteParameter("@title", DbType.String, title.Trim()),
                SQLiteHelper.MakeSQLiteParameter("@content", DbType.String, content.Trim()),
                SQLiteHelper.MakeSQLiteParameter("@addtime", DbType.DateTime,DateTime.Now)
            };
        return SQLiteHelper.ExecuteSql(sql, parameters);  //调用SQLiteHelper文件中方法,执行数据库插入
    }

6,手写Sql输出数据(删)

protected void Page_Load(object sender, EventArgs e)
        {
            user user = new user();
            user.id = 15;
            DeleteColumn(user);
        }

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

  ---不用Dapper,删除一条数据,代码如下(4行):

  public static int del_news(string newid)
    {
        string sql = "delete from news where newid=@newid";
        SQLiteParameter[] parameters =
            {
                SQLiteHelper.MakeSQLiteParameter("@newid", DbType.String, newid.Trim())
            };
        return SQLiteHelper.ExecuteSql(sql, parameters);
    }

7,手写Sql更新数据(改)

protected void Page_Load(object sender, EventArgs e)
        {
            user user = new user();
            user.id = 14;
            user.name = "Dapper03";
            user.address = "太康";
            user.age = "25";
            UpdateColumn(user);
        }

//更新一个类别:
        public int UpdateColumn(user user)
        {
            using (IDbConnection conn = SQLiteHelper.OpenConnection())
            {
                const string query = "update user set name=@name,address=@address,age=@age where id=@id";
                return conn.Execute(query, user);
            }
        }

8,手写Sql查询数据(查)

protected void Page_Load(object sender, EventArgs e)
        {
            user user = new user();
            user.id = 14;
            user=SelectColumn(user.id);
            Context.Response.Write(user.name+"|"+user.address+"|"+user.age);
            Context.Response.End();
        }

//获取单个user对象。
        public user SelectColumn(int user_id)
        {
            using (IDbConnection conn = SQLiteHelper.OpenConnection())
            {
                const string query = "select * from user where id=@id";
                return conn.Query<user>(query, new {id = user_id}).SingleOrDefault<user>();  //这里用的是linq语法,所以必须引用System.Linq;
            }
        }

  ---这里我们传递了一个参数给Query方法,参数可以是任何对象,其属性在查询中与sql的参数匹配,由于Query总是返回一个集合,我们只需调用SingleOrDefault方法,因为我们知道总是返回0或1行.

  //获取user对象的集合。
        public IEnumerable<user> SelectUsers()
        {
            using (IDbConnection conn = SQLiteHelper.OpenConnection())
            {
                const string query = "select * from user order by id asc";
                return conn.Query<user>(query, null);
            }
        }

    protected void Page_Load(object sender, EventArgs e)
        {
            IEnumerable<user> list = SelectUsers();
            foreach (var i in list)
            {
                Context.Response.Write(i.name + "|" + i.address + "|" + i.age);
                Context.Response.Write("<br/>");
            }
            Context.Response.End();
        }

五,如果想直接插入一个实体对象,Sql语句都不要了,可以在Nuget上下载Dapper的扩展包--->Dapper.SimpleCRUD安装包。(crud即增查改删)

  ---使用Dapper.SimpleCRUD时,两个注意点,1是直接插入实体,类代码要改:

  public class user
    {
        [Key]    //主键值前加个key
        public int id { get; set; }
        public string name { get; set; }
        public string address { get; set; }
        public string age { get; set; }
    }

       ///<summary>
         ///实体插入数据
         ///</summary>
        public int? InsertWithEntity()
        {
            using (var conn = SQLiteHelper.OpenConnection())
            {
                var user = new user { name = "Dapper02", address = "周口",age="22"};
                return conn.Insert(user);
            }
        } 

  ---2是使用sqlite数据库时,会报错!错误内容如下,因为sqlite不支持scope_identity函数,没有这个函数:

SQL logic error or missing database
no such function: SCOPE_IDENTITY

5,就是这么简单,直接在例子中嵌入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/>");
    }
}

//将一级类别和二级类别显示在页面上,如果使用一个递归,很容易实现无限级分类(你懂的)。

7,//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】.

8,//接下来向数据库里添加一个类别
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);
}
9,下面介绍一下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;
    }
}

 
 

ORM框架之------Dapper,Net下无敌的ORM的更多相关文章

  1. Net下无敌的ORM

    Dapper ORM 用法—Net下无敌的ORM http://www.renfb.com/blog/2011/Article/335 假如你喜欢原生的Sql语句,又喜欢ORM的简单,那你一定会喜欢上 ...

  2. 【.NET框架】Dapper ORM 用法—Net下无敌的ORM

    假如你喜欢原生的Sql语句,又喜欢ORM的简单,那你一定会喜欢上Dapper这款ROM.点击下载 Dapper的优势: 1,Dapper是一个轻型的ORM类.代码就一个SqlMapper.cs文件,编 ...

  3. Dapper ORM 用法—Net下无敌的ORM(转)

    假如你喜欢原生的Sql语句,又喜欢ORM的简单,那你一定会喜欢上Dapper这款ROM.点击下载Dapper的优势:1,Dapper是一个轻型的ORM类.代码就一个SqlMapper.cs文件,编译后 ...

  4. Dapper ORM 用法—Net下无敌的ORM

    假如你喜欢原生的Sql语句,又喜欢ORM的简单,那你一定会喜欢上Dapper这款ROM.点击下载Dapper的优势:1,Dapper是一个轻型的ORM类.代码就一个SqlMapper.cs文件,编译后 ...

  5. 轻量级ORM框架初探-Dapper与PetaPoco的基本使用

    一.EntityFramework EF是传统的ORM框架,也是一个比较重量级的ORM框架.这里仍然使用EF的原因在于为了突出轻量级ORM框架的性能,所谓有对比才有更优的选择. 1.1 准备一张数据库 ...

  6. 【快速入门ORM框架之Dapper】大牛勿进系列

    前言:dapper是什么?Dapper是.NET下一个micro的ORM,它和Entity Framework或Nhibnate不同,属于轻量级的,并且是半自动的.也就是说实体类都要自己写.它没有复杂 ...

  7. 轻量级高性能ORM框架:Dapper高级玩法

    Dapper高级玩法1: 数据库中带下划线的表字段自动匹配无下划线的Model字段. Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true; 备 ...

  8. 轻量级ORM框架:Dapper中的一些复杂操作和inner join应该注意的坑

    上一篇博文中我们快速的介绍了dapper的一些基本CURD操作,也是我们manipulate db不可或缺的最小单元,这一篇我们介绍下相对复杂 一点的操作,源码分析暂时就不在这里介绍了. 一:tabl ...

  9. Mego(2) - NET主流ORM框架分析

    接上文我们测试了各个ORM框架的性能,大家可以很直观的看到各个ORM框架与原生的ADO.NET在境删改查的性能差异.这里和大家分享下我对ORM框架的理解及一些使用经验. ORM框架工作原理 典型ORM ...

随机推荐

  1. C++代码风格指南总结

    C++代码风格指南 代码风格的重要性 今天我收到thougthwork笔试没过的消息, 心里确实很难受, 然后师兄说我代码写得很糟糕 细想一下, 我写代码确实是随心所欲, 并没有遵循什么规范; 所以现 ...

  2. linux mysql 定时备份 使用crontab

    第一步:在服务器上配置备份目录代码: mkdir /var/lib/mysqlbackup cd /var/lib/mysqlbackup 第二步:编写备份脚本代码:  vi dbbackup.sh ...

  3. 讨论HTTP POST 提交数据的几种方式

    转自:http://www.cnblogs.com/softidea/p/5745369.html HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS.GET.HEAD.POST.PU ...

  4. 一种简单的生产环境部署Node.js程序方法

    最近在部署Node.js程序时,写了段简单的脚本,发觉还挺简单的,忍不住想与大家分享. 配置文件 首先,本地测试环境和生产环境的数据库连接这些配置信息是不一样的,需要将其分开为两个文件存储 到conf ...

  5. eclipse:显示堆内存

    如下图 :

  6. how to get address of member function

    see:http://www.cplusplus.com/forum/general/136410/ & http://stackoverflow.com/questions/8121320/ ...

  7. 查看和解除Linux系统对用户使用资源的限制

    查看当前系统资源限制 ulimit -a   设置用户的最大进程数(重启后失效) ulimit -u 1024   设置用户可以打开的最大文件句柄数(重启后失效) ulimit -n 65530   ...

  8. windows IDEA注册码激活方法(2018.4.8)靠谱可用!

    简介 intellij idea 2018注册码是针对intellij idea 2018软件研发推出,它的使用需要和激活补丁一起使用,安装包里面也拥有破解补丁, 所有无需在进行单独的下载:不过如果选 ...

  9. yum报错:Error: Multilib version problems found. This often means that the root

    使用yum安装一些依赖库报错: yum -y install gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel 错误信 ...

  10. Spring+SpringMVC+MyBatis的整合

    1.基本概念   1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-On ...