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安裝。
如果環境是在.NET4.5環境下進行的編譯,最新版的Dapper可能與之不相容,會出現以下報錯:
你可以安裝一個低版本的Dapper來規避此問題,我採用的是1.40.0版本的Dapper,親測可用。
一、建立與資料庫表對應的實體類
此前的文章忘記介紹此步驟,特意補充。
利用SQLite的視覺化工具DB Browser for SQLite 建立資料庫檔案SQLDB.db,並建立以“people”為名稱的表,配置好資料型別,以ID作為主鍵。
然後我們需要建立一個實體類(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<PeopleModel> peoples
。
刪除的操作是根據其主鍵ID,所以刪除的批量操作視情況而定,根據DataGridViewRow的單元格屬性選擇需要進行的批量操作。
四、窗體程式碼
建立窗體如上圖所示,右側為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物件
在兩個表上同時執行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);
}
}