iT邦幫忙

5

[鼠年全馬鐵人挑戰] Week02 - Dapper用法筆記 part1

餅乾 2020-02-12 16:36:4423696 瀏覽

現在工作上常常會需要用到串接資料庫丟資料到前端做呈現
但未來我想走的方向是專職前端,後端程式大概會越來越少碰到
所以想趁現在還記得怎麼使用的當下,趕快把他紀錄起來
免得我可憐的金魚腦袋忘了之後又無從回想起
/images/emoticon/emoticon02.gif/images/emoticon/emoticon02.gif/images/emoticon/emoticon02.gif


Dapper是什麼??

Dapper 是.net平台的ORM(object-relational mapping)套件
主要功能包含:

  • Speedy and high performance(快速且高效能)
  • Fewer lines of code(極少代碼行)
  • Object mapper(對應物件)
  • Choice of static/dynamic object binding(綁定靜態或動態物件)
  • Easy handling of SQL query(輕鬆的SQL處理)
  • Multiple query support(支援多筆處理)
  • Support and easy handling of stored procedures(支援且輕鬆的處理預存程序)
  • Operating directly on IDbConnection interface(抱歉這個功能我不理解xD)
  • Bulk data insert functionality(大量資料新增)
    資料來源: 維基百科:Dapper_ORM

看完官方介紹的功能後,應該還是感覺不出來他的強大吧? 沒關係待我娓娓道來

安裝

首先先到 nuget管理套件頁面 -> 瀏覽頁中搜尋 Dapper -> 正常都出現在第一個
https://ithelp.ithome.com.tw/upload/images/20200212/20118686P8P9uWxTQS.jpg

這邊要注意一個地方,右側都會有套件的詳細資訊,其中最下面會寫相依性,要看是不是有符合你專案使用的版本
https://ithelp.ithome.com.tw/upload/images/20200212/20118686EpnMv7KxzU.jpg

之前在維護前人的程式時,想說可以幫他把程式碼優化,就去安裝Dapper,結果一直安裝不成功,後來才發現原來他的.netFramework版本是4.0,而自動安裝都是裝最新版本,就這樣傻傻浪費了一段時間
/images/emoticon/emoticon10.gif/images/emoticon/emoticon10.gif/images/emoticon/emoticon10.gif

安裝完之後就可以開始來使用囉~

Dapper 使用

Dapper有分增刪改查的方式,其中增刪改用法相同
在使用前都要先搖一搖,要先在程式碼最上方先引用他:

using Dapper;

查詢

那就先從最常使用的查詢開始吧~
先來看看原本的查詢語法,以Oracle為例:

// 宣告連線字串
private string connstr = WebConfigurationManager.ConnectionStrings["oracledbconn"].ConnectionString;
// 宣告OleDb連線 並帶入連線字串
OleDbConnection oleDbConnection = new OleDbConnection(connstr);

// 宣告OleDb命令集
OleDbCommand oleDbCommand = new OleDbCommand();
oleDbCommand.CommandType = CommandType.Text; 
oleDbCommand.CommandText = "SELECT EmpID, EmpName FROM Employees";  // 設定SQL字串
oleDbCommand.Connection = oleDbConnection;  // 設定連線

// 宣告OleDb接口
OleDbDataAdapter oleDbDataAdapter = new OleDbDataAdapter(oleDbCommand); 

// 宣告DataTable
DataTable dataTable = new DataTable();

// 開始對資料庫存取 並將資料從接口轉到DataTable
oleDbConnection.Open();
oleDbDataAdapter.Fill(dataTable);
oleDbConnection.Close();

沒有誇張,程式碼就是這麼多
而再怎麼簡化,最少都還是要宣告OleDbCommand,然後設定SQL字串,最後用DataTable裝值,再用程式碼去跑要回傳前端的資料
這還只是進行存取一次資料庫而已,看完都暈了/images/emoticon/emoticon06.gif/images/emoticon/emoticon06.gif/images/emoticon/emoticon06.gif

再來,來看看Dapper的標準版寫法:

using (OleDbConnection oleDbConnection = new OleDbConnection(connstr))
{
    string querystr = "SELECT EmpID, EmpName FROM Employees";
	var result = oleDbConnection.Query(querystr).ToList();
}

結束

真的就是這麼簡單!!!
一樣要用OleDbConnection,一樣要設定SQL字串,但Dapper只要短短五行就解決
是不是hen棒棒/images/emoticon/emoticon12.gif

加入視圖模型(ViewModel)

上面標準版在使用上取出值以及日後維護上比較麻煩,例如假設網頁在多個動作上都會要取EmpID欄位,就會寫到多次下面的語法去取值:

    var v_empid = result[0].EMPID;

但假設某天因為什麼變動需要更改欄位名稱,這多次取值就需要全部改寫,非常耗時且麻煩
那有沒有簡單的方法? 當然有,就是加入視圖模型(ViewModel)
首先建立一個class名稱為EmployeesEmployees內加入存取子名稱為EmpID(名稱要跟SQL字串內的欄位名稱相同):

public class Employees
{
    public string EmpID { get; set; }
}

這時標準版就可以改寫成如下,從資料庫取回來的資料會自動把欄位名稱做對應到ViewModel的存取子名稱:

using (OleDbConnection oleDbConnection = new OleDbConnection(connstr))
{
    string querystr = "SELECT EmpID, EmpName FROM Employees";
	List<Employees> employees = oleDbConnection.Query<Employees>(querystr).ToList();
}

日後如果碰上上述要改欄位名稱的情況,就只要修改ViewModel即可,既省時又省力。

加入參數

先提一下原本加入參數的寫法,比較起來才有感
假設今天只要找姓名叫做王小明,且年齡50歲,性別性,職業是工程師的員工:

string empname = "王小明";
string age = "50";
string sex = "男";
string job = "工程師";
// 加入參數的動作會在"宣告OleDb命令集"時加入
// 宣告OleDb命令集
OleDbCommand oleDbCommand = new OleDbCommand();
oleDbCommand.CommandType = CommandType.Text; 
oleDbCommand.CommandText = "SELECT EmpID, EmpName FROM Employees WHERE EmpName = :EmpName AND Age = :Age AND Sex = :Sex AND Job = :Job";  // 設定SQL字串
oleDbCommand.Parameters.AddWithValue("EmpName", empname);
oleDbCommand.Parameters.AddWithValue("Age", age);
oleDbCommand.Parameters.AddWithValue("Sex", sex);
oleDbCommand.Parameters.AddWithValue("Job", job);

有發現了嗎? 條件越多,就要加入越多行一模一樣的程式碼,程式碼行數一多起來,先不管好不好讀,看到就先暈了
我自己就常常遇到在加入參數時,少寫一行結果Debug一直跳錯說找不到參數值.../images/emoticon/emoticon20.gif
順口一提,上面寫法是正統加入參數的寫法,很多工程師貪圖方便都直接把參數用串接的寫進字串內,像這樣:

oleDbCommand.CommandText = "SELECT EmpID, EmpName FROM Employees WHERE EmpName = '" + empname + "' AND Age = '" + age + "' AND Sex = '" + sex + "' AND Job = '" + job + "'";  // 設定SQL字串

也不能說寫錯,但這種寫法根本鬧,就是叫駭客趕快來弄你的資料庫...
我朋友親身經歷的,他當時還是菜鳥工程師,在XX證卷上班,使用這種語法來介接資料庫,結果客戶資料全部被駭客盜走公開到暗網去/images/emoticon/emoticon04.gif /images/emoticon/emoticon04.gif /images/emoticon/emoticon04.gif
而這種攻擊有個專有名詞叫SQL injection,有興趣的可以去估狗看看

題外話講太多了,回來看看如果使用Dapper要怎麼寫加入參數

using (OleDbConnection oleDbConnection = new OleDbConnection(connstr))
{
    string querystr = "SELECT EmpID, EmpName FROM Employees WHERE EmpName = :EmpName AND Age = :Age AND Sex = :Sex AND Job = :Job";
    // 相同的function,但SQL字串的參數後面再加入一個參數放物件,物件內放參數
	List<Employees> employees = oleDbConnection.Query<Employees>(querystr, new { EmpName = empname, Age = age, Sex = sex, Job = job }).ToList();
}

比起原本寫法更簡潔有力了
那這種方式能阻止SQL injection攻擊嗎? 當然可以,這種參數化的SQL字串寫法,目前被視為最有效可預防SQL injection攻擊的方式
維基百科-參數化查詢

另外Dapper還有多個變化型的查詢寫法,像是:

  • QueryFirst(): 取得第一筆,有多筆時一樣只取一筆,沒有資料時回傳錯誤
  • QuerySingle(): 只取一筆唯一的資料,有多筆或沒有資料時回傳錯誤

其他還有很多種查詢,可以到他的GitHub看看


這一趴就到這吧!!
增刪改以及其他像是優缺點等等,留到下一趴再來做紀錄 ya

若有錯誤麻煩大神們糾正,非常感謝~/images/emoticon/emoticon41.gif/images/emoticon/emoticon41.gif/images/emoticon/emoticon41.gif


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Jason
iT邦新手 4 級 ‧ 2022-01-27 09:43:29

使用Dapper,但參數是設定"SELECT EmpID, EmpName FROM Employees WHERE EmpName = '" + empname + "' AND Age = '" + age + "' AND Sex = '" + sex + "' AND Job = '" + job + "'"; // 設定SQL字串
Dapper有防SQL injection攻擊嗎?

餅乾 iT邦新手 4 級 ‧ 2022-01-27 14:37:29 檢舉

這種字串組合的寫法本身就很容易被SQL injection

要使用後面那段說明的[冒號+參數名稱]的方式
例如 :EmpName、:Age

另外,Dapper本身不會防SQL injection攻擊
是OleDb的參數化SQL寫法才有防攻擊唷~

這篇提到是因為常常有新手直接組字串SQL
然後就...就初四了阿北

我要留言

立即登入留言