C#利用Dapper实现对SQLite的操作

前言

近几天借助C#对SQLite的学习,算是对数据库刚入门吧,三天前写了一篇C#利用System.Data.SQLite实现对SQLite的操作,其中方法是基于System.Data.SQLite.dll的程序包,后来在youtube和infoworld上看到利用Dapper程序包对数据库操作更简单、快捷,在其基础之上自己又增加了一些用法,以下是参考视频和文档:

参考视频:https://www.youtube.com/watch?v=ayp3tHEkRc0
参考文档:https://www.infoworld.com/article/3025784/application-development/how-to-work-with-dapper-in-c.html

ORM介绍

介绍Dapper之前不得不提及ORM,ORM是什么呢?

从字面理解,O是Object,对象;R是Relation,关系;M是Mapping,映射。所以,用一句话概括就是:ORM是一种对象关系映射的技术。

我们平时所使用的大多数编程模型都是面向对象编程,就是把我们研究的问题抽象出来分解成一个个对象,对象有属性,方法等等,我们操作的是对象。

而我们平时所使用的数据库是关系型数据库,他是从集合论等数学知识发展过来的,他讲究集合,映射,六大范式等等,跟我们的面向对象思想的封装继承多态不同,这两者之间有着根本性的差异。

所以我们就存在一个问题,怎么去调和二者,如果能有一种技术把对象与数据库对应起来,我们编程就会方便许多。于是,ORM应运而生,他就是为了解决对象与数据库之间的差异所产生的一门技术,用他可以把对象与数据库建立一种映射,对于业务层的程序员,他不用管数据库的结构,他只需要专注于他的业务逻辑去操作对象。至于对象怎么去变成元组进入数据库,以及怎么从数据库取数据变成对象,那是ORM自动解决的。

所以,ORM为对象关系映射器,它直接将数据库映射到C#对象。

有很多ORM框架可用,Dapper是其中之一,被称为ORM之王。

Dapper介绍与安装

功能:
1、速度快,性能好;
2、更少的代码行
3、对象映射
4、静态对象绑定
5、动态对象绑定
6、易于处理Sql语句
7、易于处理存储过程
8、直接操作IDBConnection类,该类直接向数据库提供平滑性和运行查询,而不是像在EF和ADO.NET中那样使用各种对象传递数据。
9、多个查询支持
10、支持存储过程
11、批量处理数据插入
12、允许基于多个输入获取多个数据

安装:
鼠标右击项目下面的引用选项,进入NuGet,输入Dapper安装。

C#利用Dapper实现对SQLite的操作

如果环境是在.NET4.5环境下进行的编译,最新版的Dapper可能与之不兼容,会出现以下报错:

C#利用Dapper实现对SQLite的操作

你可以安装一个低版本的Dapper来规避此问题,我采用的是1.40.0版本的Dapper,亲测可用。

一、创建与数据库表对应的实体类

此前的文章忘记介绍此步骤,特意补充。
利用SQLite的可视化工具DB Browser for SQLite 创建数据库文件SQLDB.db,并创建以“people”为名称的表,配置好数据类型,以ID作为主键。

C#利用Dapper实现对SQLite的操作

然后我们需要创建一个实体类(POCO类),下面是与数据库SQLDB中people表相对应的实体类PeopleModel,其中包含表中含有的几个字段:

 public class PeopleModel
    {
        public int ID { get; set; }
        public string MName { get; set; }
        public int Age { get; set; }
        public string Sex { get; set; }
        public string Phone { get; set; }
    }

二、配置路径

App.config下配置数据库路径

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <connectionStrings>
      <add name="sqlDB" connectionString="data source=H:\C#\DemoDB\DemoDB\bin\Debug\SQLDB.db;version=3;"/>
    </connectionStrings>
</configuration>

在项目中访问connectionStrings标签

 private static string LoadConnectString(string id = "sqlDB")
 {
     return ConfigurationManager.ConnectionStrings[id].ConnectionString;
 }

三、Dapper对于SQLite的基本操作

Dapper如何工作

主要包含三个步骤
第一步:使用连接字符串创建一个IDBConnection对象;
第二步:编写一个查询并将其存储在一个普通的字符串变量中;
第三步:调用db.execute()并传递查询,完成。

查询数据
Dapper中的扩展方法Query()能够让你从数据库中检索数据并填充到对象模型中。

public static List<PeopleModel> LoadPeople()
        {
            using (IDbConnection cnn = new SQLiteConnection(LoadConnectString()))
            {
                cnn.Open();
                var output = cnn.Query<PeopleModel>("select * from people", new DynamicParameters());
                return output.ToList();
            }
        }

保存数据
Dapper中的Execute()方法可以用于向数据库中插入,更新,删除数据。这个方法会返回一个整数,表示在执行查询时受到影响的行数。

 public static void SavePerson(PeopleModel people)
        {
            using (IDbConnection cnn = new SQLiteConnection(LoadConnectString()))
            {
                cnn.Execute("insert into people (MName,Age,Sex,Phone) values(@MName,@Age,@Sex,@Phone)", people);
            }
        }

修改数据

public static void UpdatePerson(PeopleModel people,int id)
        {
            using (IDbConnection cnn = new SQLiteConnection(LoadConnectString()))
            {
                cnn.Execute("update people set MName = @MName,Age = @Age,Sex = @Sex,Phone = @Phone where ID="+id,people);
            }
        }

删除数据

 public static int Delete(int id)
        {
            using (IDbConnection cnn = new SQLiteConnection(LoadConnectString()))
            {
               return cnn.Execute("delete from people where ID="+id);
            }
        }

批量操作
批量操作就把对象由单个改为多个即可,即把PeopleModel people改为List peoples。
删除的操作是根据其主键ID,所以删除的批量操作视情况而定,根据DataGridViewRow的单元格属性选择需要进行的批量操作。

四、窗体代码

C#利用Dapper实现对SQLite的操作

建立窗体如上图所示,右侧为DataGridViewRow控件。

新建泛型集合

 List<PeopleModel> people = new List<PeopleModel>();

绑定数据源

private void WireUpPeopleList()
        {
            dataGridView1.DataSource = null;
            dataGridView1.DataSource = people;      
        }

数据刷新函数

private void LoadPeopleList()
        {
            people = SqliteHelper.LoadPeople();  
            WireUpPeopleList();
        }

添加/修改
其中双击特定行会把数据返回至填单里,根据txtID里的信息判断是否进行修改行为。

private void btn_Add_Click(object sender, EventArgs e)
        {
            PeopleModel p = new PeopleModel();
            
            p.MName = txtName.Text;
            p.Age = Convert.ToInt32(txtAge.Text);
            p.Sex = btnBoy.Checked ? "男" : "女";
            p.Phone = txtPhone.Text;
            if (txtID.Text.Equals("添加时无编号"))
            {
                SqliteHelper.SavePerson(p);
            }
            else
            {
                SqliteHelper.UpdatePerson(p,Convert.ToInt32(txtID.Text));
            }
            txtName.Text = "";
            txtAge.Text = "";
            txtPhone.Text = "";
            txtID.Text = "添加时无编号";
        } 

双击操作
返回信息至填单,“添加”按钮变为“修改”

private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
            txtID.Text = row.Cells[0].Value.ToString();
            txtName.Text = row.Cells[1].Value.ToString();
            txtAge.Text = row.Cells[2].Value.ToString();
            txtPhone.Text = row.Cells[4].Value.ToString();
            if (row.Cells[3].Value.ToString().Equals("男"))
            {
                btnBoy.Checked = true;
            }
            else
            {
                btnGirl.Checked = true;
            }
            btn_Add.Text = "修改";
        }

删除操作

private void btn_Delete_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.dataGridView1.SelectedRows.Count > 0)
                {
                    DialogResult result = MessageBox.Show("确定要删除吗?", "提示", MessageBoxButtons.OKCancel);
                    if (result == DialogResult.Cancel)
                    {
                        return;
                    }
                    int x = int.Parse(dataGridView1.SelectedRows[0].Cells[0].Value.ToString());
                    SqliteHelper.Delete(x);
                    LoadPeopleList();
                }
                else
                {
                    MessageBox.Show("请选择需要删除的行", "提示", MessageBoxButtons.OK);
                }
            }
            catch(Exception x)
            {
                MessageBox.Show(this, x.Message, "Error", MessageBoxButtons.OK);
            }
            
        }

五、Dapper的复杂操作

查询的In操作

public static List<PeopleModel> QueryIn()
{
    using (IDbConnection connection = new SqlConnection(connectionString))
    {
        var sql = "select * from people where id in @ids";
        //参数类型是Array的时候,dappper会自动将其转化
        return connection.Query<Person>(sql, new { ids = new int[2] { 1, 2 }, }).ToList();
    }
}

public static List<PeopleModel> QueryIn(int[] ids)
{
    using (IDbConnection connection = new SqlConnection(connectionString))
    {
        var sql = "select * from people where id in @ids";
        //参数类型是Array的时候,dappper会自动将其转化
        return connection.Query<Person>(sql, new { ids }).ToList();
    }
}

处理多个表
我们也会遇到一次需要处理多个表的需求,例如一次查询多个表或者以外键获取数据
1、我们可以用Dapper同时访问多个表,并且十分平滑
2、传递对象列表,Dapper本事可以识别出是批量插入
3、根据各种参数获取数据,Dapper会自动将数组转换成CSV,并返回一个List对象

C#利用Dapper实现对SQLite的操作

在两个表上同时执行CRUD操作,使用相同的ContactId,即Contacts表中的主键,Address表中的外键,现在让我们通过传递Id从Contacts表和Address表中获取多条数据:

static IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["SQLDB"].ConnectionString);
string query = "select * from contacts where id = @id ; select * from address where ContactId = @id;";
using (var multipleresult = db.QueryMultiple(query, new { id = 1 }))
            {
                var contact = multipleresult.Read<Contact>().SingleOrDefault();
                var Addresses = multipleresult.Read<Address>().ToList();
                if (contact != null && Addresses != null)
                {
                    contact.Addresses.AddRange(Addresses);
                }
            }

使用存储过程访问数据库
以下为sql的一个存储过程:

Use ContactDB
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[sp_GetContact_Address]  
    @Id int 
AS
BEGIN
select * from contacts where id = @Id ;   
select * from Address where ContactId = @Id; 
END
GO

用Dapper调用存储过程

第一步同上

在这里不需要写任何的query语句,相反的我们将调用数据库内的存储过程
在这里将做的更改是传递一个存储过程的名称而不是查询语句,并传递一个名称为command type的参数。

using (var multipleresult = db.QueryMultiple("sp_GetContact_Address", new { id = 1 }, commandType: CommandType.StoredProcedure))
            {
                var contact = multipleresult.Read<Contact>().SingleOrDefault();
                var Addresses = multipleresult.Read<Address>().ToList();
                if (contact != null && Addresses != null)
                {
                    contact.Addresses.AddRange(Addresses);
                }
            }

原文出处:CSDN【BBBMouse】

原文链接:https://blog.csdn.net/weixin_41732430/article/details/83871216

本文观点不代表Dotnet9立场,转载请联系原作者。

发表评论

登录后才能评论