C# 数据操作系列 - 17 Dapper ——号称可以与ADO.NET 同台飙车的ORM_c# dapper update-程序员宅基地

技术标签: c#  C#教程  

  1. 前言
    之前四篇介绍了一个国内开发者开发的优秀框架SqlSugar,给我们眼前一亮的感觉。这一篇,我们将试试另一个出镜率比较高的ORM框架-Dapper。

Dapper是一个轻量级的ORM框架,其以高速、简单易用为特点。在某些时候,效率甚至可以与ADO.NET 媲美。那么,吹得天花乱坠,就让我们实际看看它的表现吧。

  1. 开始使用
    照例,先创建一个项目:DapperDemo

dotnet new console --name DapperDemo
然后切换到目录里:

cd DapperDemo
添加包支持:

dotnet add package Dapper
如果不出意外的话,目前项目中已经安装好了Dapper。现在就让我们开始愉快的使用吧。

首先,需要注意的一点是,与其他的ORM框架不同的是,Dapper需要我们手动创建一个IConnection。Dapper的所有操作都是依托于IConnection来操作,而且Dapper将其支持的方法封装成了IConnection的扩展方法。

所以,在使用之前我们需要先创建一个IConnection。为了方便演示,我把之前SqlSugar演示用过的测试数据库拿过来了,是一个SQLite,所以我们需要先安装一个SQLite的驱动:

dotnet add package Microsoft.Data.SQLite
在Program.cs中引入两个包:

using Microsoft.Data.Sqlite;
using Dapper;

在Main方法里创建一个IConnection:

using(var connection = new SqliteConnection("Data Source=./demo.db"))
{
    
    
}
  1. 多数据查询
    Dapper的查询相当简单:

var result = connection.Query(“select * from Persion”);
传入一个SQL语句,返回一个可枚举对象。如果不指定类型,将返回类型为dynamic的列表。我们来看一下Query方法的相关声明:

public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null);

public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null);

public static IEnumerable<TReturn> Query<TReturn>(this IDbConnection cnn, string sql, Type[] types, Func<object[], TReturn> map, object param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null);

我们就以最常用的三个为例,给大伙分析一下参数以及调用方式:

cnn 一个数据库连接,所以Dapper不负责管理数据库连接,这部分由我们手动管理
sql 传入的SQL语句,Dapper以IDbConnection为基础,以SQL为执行命令,所以必须我们来传入SQL语句
param 一个可以为Null的Object类型,表示SQL的参数化,Dapper对参数化做了一些优化,在SQL的参数化里,参数名映射到了object的属性上。
transaction 表示是否有IConnection级别的事务,默认为null,传入后该指令会被事务包含
buffered 缓存
commandTimeout 命令执行是否超时以及超时时间
commandType 表示命令模式 有 Text 普通模式,StoredProcedure 存储过程 ,TableDirect 表查询
splitOn 默认情况下以Id 作为两个对象之间的区分
3. 单数据查询
Dapper在数据查询方面不仅支持集合作为查询结果,还可以获取单个数据。

一共有四种方式获取单数据:

public static T QueryFirst(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null);
public static T QueryFirstOrDefault(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null);
QueryFirst 表示获取第一条查询结果,如果没有结果,则会抛出一个异常。

QueryFirstOrDefault 与QueryFirst一样,但不同的是,如果没有则不会抛出异常,而是直接返回一个该类型的默认值,数值类型的默认值为(0),引用类型的默认值为Null。

public static T QuerySingle(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null);
public static T QuerySingleOrDefault(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null);
QuerySingle也能查询单条数据作为结果,但与QueryFirst不同的是QuerySingle查询时,如果数据存在多行将会抛出异常,如果不想要异常则可以使用QuerySingleOrDefault作为查询方法。

  1. QueryMultiple
    这个另外一种查询方式,对于SQL语句来说,没有明显的限制,所以我们有时候可以传入多个查询SQL语句进去,然后分别获取来自各个表的查询数据:
string sql = "SELECT * FROM Invoice WHERE InvoiceID = @InvoiceID; SELECT * FROM InvoiceItem WHERE InvoiceID = @InvoiceID;";

using (var connection = My.ConnectionFactory())
{
    
    connection.Open();

    using (var multi = connection.QueryMultiple(sql, new {
    InvoiceID = 1}))
    {
    
        var invoice = multi.Read<Invoice>().First();
        var invoiceItems = multi.Read<InvoiceItem>().ToList();
    }
}

看一下它的基本参数和方法声明:

public static GridReader QueryMultiple(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null);

这个方法返回一个GridReader,通过Read方法获取需要的数据。

  1. 不只是查询
    Dapper当然不只有查询这一项功能,Dapper支持使用存储过程、insert、update、delete等其他的SQL语句进行操作数据库。使用方式:
string sql = "Invoice_Insert";

using (var connection = My.ConnectionFactory())
{
    
    var affectedRows = connection.Execute(sql,
        new {
    Kind = InvoiceKind.WebInvoice, Code = "Single_Insert_1"},
        commandType: CommandType.StoredProcedure);
    var affectedRows2 = connection.Execute(sql,
        new[]
        {
    
            new {
    Kind = InvoiceKind.WebInvoice, Code = "Many_Insert_1"},
            new {
    Kind = InvoiceKind.WebInvoice, Code = "Many_Insert_2"},
            new {
    Kind = InvoiceKind.StoreInvoice, Code = "Many_Insert_3"}
        },
        commandType: CommandType.StoredProcedure
    );
}


示例就是使用存储过程的例子。


string sql = "INSERT INTO Customers (CustomerName) Values (@CustomerName);";

using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
    
    var affectedRows = connection.Execute(sql, new {
    CustomerName = "Mark"});

    Console.WriteLine(affectedRows);

    var customer = connection.Query<Customer>("Select * FROM CUSTOMERS WHERE CustomerName = 'Mark'").ToList();

    FiddleHelper.WriteTable(customer);
}
//== 多次插入
string sql = "INSERT INTO Customers (CustomerName) Values (@CustomerName);";

using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
    
    connection.Open();

    var affectedRows = connection.Execute(sql,
    new[]
    {
    
    new {
    CustomerName = "John"},
    new {
    CustomerName = "Andy"},
    new {
    CustomerName = "Allan"}
    }
);

这是执行插入的示例。

string sql = "UPDATE Categories SET Description = @Description WHERE CategoryID = @CategoryID;";

using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
                
    var affectedRows = connection.Execute(sql,new {
    CategoryID = 1, Description = "Soft drinks, coffees, teas, beers, mixed drinks, and ales"});

    Console.WriteLine(affectedRows);
}

更新。

string sql = "DELETE FROM Customers WHERE CustomerID = @CustomerID";

using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
                
    var affectedRows = connection.Execute(sql, new {
    CustomerID = 1});

    Console.WriteLine(affectedRows);
}

删除。

Execute没什么好说的,基本就是执行SQL语句的形式完成增删改成等操作。

值得注意的是:

public static IDataReader ExecuteReader(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null);

返回一个IDataReader实例,这个实例可以给DataTable填充vb.net教程数据,使用方法如下:

DataTable table = new DataTable();
table.Load(reader);
以及:

public static T ExecuteScalar<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null);

这个方法是返回查询结果的第一行第一列的元素。

  1. 总结
    如果单说Dapper的话,并没有太多好说的。不过Dapper是真的快,在实际开发中有时候会用Dapper作为EF Core的一个补充。

当然了,Dapper还有很多其他的插件,使用那些插件c#教程可以为Dappe带来非一般的提升。我们下一篇将介绍一下Dapper的插件。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/chinaherolts2008/article/details/111950978

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法