C# 資料操作系列 - 18 讓Dapper更強的外掛

月影西下發表於2020-05-28

0. 前言

在前一篇中我們講到了Dapper的應用,但是給我們的感覺Dapper不像個ORM更像一個IDbConnection的擴充套件。是的,沒錯。在實際開發中我們經常用Dapper作為對EF Core的補充。當然了Dapper並不僅僅只有這些,就讓我們通過這一篇文章去讓Dapper更像一個ORM吧。

1. Dapper Contrib

Dapper Contrib 擴充套件了Dapper對於實體類的CRUD方法:

安裝方法:

命令列:

dotnet add package Dapper.Contrib

NuGet:

Install-Package Dapper.Contrib

使用:

using Dapper.Contrib.Extensions;

這個是一個使得Dapper功能更強大的擴充套件包,因為支援了CRUD,所以需要對實體類新增配置,該擴充套件包使用Attribute作為依據進行相關對映配置:

[Table("Model")]
public class Model
{
    [Key]
    [ExplicitKey]
    public int Id{get;set;}
    [Computed]
    public int Count {get;set;}
    [Write]
    public String Name{get;set;}
}

這是所有的配置,Table用來宣告是一個表,必須指定表名,Key表示該屬性是資料庫主鍵,ExplicitKey表示這個屬性是資料庫中顯示設定的主鍵,Computed表示該欄位是一個計算欄位,Write表示該欄位可以設定值進去。需要注意的是: Key和ExplicitKey這兩個不能同時標註在一個屬性上。

那麼接下來,我們看看它擴充套件了哪些方法:

插入單個物件:

public static long Insert<T>(this IDbConnection connection, T entityToInsert, IDbTransaction transaction = null, int? commandTimeout = null) where T : class;

其中 transcation表示事務,如果指定事務,資料的提交將由事務控制,該方法會返回插入物件的主鍵(如果物件主鍵是數字型別)或者返回一個待插入列表中已插入的行數。

獲取單個物件:

public static T Get<T>(this IDbConnection connection, [Dynamic] dynamic id, IDbTransaction transaction = null, int? commandTimeout = null) where T : class;

通過傳入主鍵,獲取一個資料

獲取所有資料:

public static IEnumerable<T> GetAll<T>(this IDbConnection connection, IDbTransaction transaction = null, int? commandTimeout = null) where T : class;

更新資料:

Dapper Contrib 提供了一個用來更新的方法:

public static bool Update<T>(this IDbConnection connection, T entityToUpdate, IDbTransaction transaction = null, int? commandTimeout = null) where T : class;

這個方法比較有意思的是

var entity = connection.Get<Model>(1);
entity.Name = "測試1";
connection.Update(entity);

var models = connection.GetAll<Model>();
foreach(var m in models)
{
    Console.WriteLine(m);
    m.StringLength ++;
}
connection.Update(models.AsList());

都可以,並不會報錯。

不過需要注意的是,如果需要更新的例項沒有指定主鍵值(主減屬性沒有賦值),則不會有任何行發生更新。而且在更新的時候,會更新所有列,不會因為不賦值就不更新。

刪除方法有兩個:

public static bool Delete<T>(this IDbConnection connection, T entityToDelete, IDbTransaction transaction = null, int? commandTimeout = null) where T : class;
public static bool DeleteAll<T>(this IDbConnection connection, IDbTransaction transaction = null, int? commandTimeout = null) where T : class;

刪除也是傳入一個實體類,一樣也只是需要主鍵有值,如果沒有找到主鍵對應的資料,則不會有任何變化。Delete與Update一樣,如果傳入一個List集合也是可以的。

2. Dapper Transaction

這個包擴充套件了Dapper的事務處理能力。雖然是Dapper的擴充套件包,但是是給IConnection新增了一個擴充套件方法。使用示例如下:

dotnet add package Dapper.Transaction

老規矩,記得先把包加進來。

然後程式碼是這樣的:

using Dapper.Transaction;
using(var connection = new SqliteConnection("Data Source=./demo.db"))
{
    connection.Open();
    var transcation = connection.BeginTransaction();
    // 編寫業務程式碼
    transcation.Commit();
}

如果使用Dapper Transaction,需要先呼叫 connection.Open()來確保連線是開啟狀態。

transcation這個物件可以當做普通的DbTranscation物件,傳給Dapper的方法來使用,也可以當做一個開啟了事務的Dapper客戶端來使用。也就是說,Dapper對IDbConnection擴充套件的方法,在這個包對IDbTranscation也擴充套件了響應的方法:

image-20200527155732804

3. Dapper Plus

這個外掛是Dapper上用來處理巨量資料的外掛,但這是個收費版的外掛,不過每個月都有一定的試用期限。想試試的可以下一下:

dotnet add package Z.Dapper.Plus

使用:

using Z.Dapper.Plus;

這個外掛在使用之前需要先配置實體類與資料庫之間的對映關係:

DapperPlusManager.Entity<Customer>().Table("Customers");
DapperPlusManager.Entity<Supplier>().Table("Suppliers").Identity(x => x.SupplierID);

該外掛支援四組大批量處理方式:

  • Bulk Insert
  • Bulk Update
  • Bulk Merge
  • Bulk Delete
// STEP MAPPING
DapperPlusManager.Entity<Supplier>().Table("Suppliers").Identity(x => x.SupplierID);
DapperPlusManager.Entity<Product>().Table("Products").Identity(x => x.ProductID);

// STEP BULKINSERT
using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
    connection.BulkInsert(suppliers).ThenForEach(x => x.Products.ForEach(y => y.SupplierID =  x.SupplierID)).ThenBulkInsert(x => x.Products);
}

// STEP BULKUPDATE
using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
    connection.BulkUpdate(suppliers, x => x.Products);
}

// STEP BULKMERGE
using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
    connection.BulkMerge(suppliers).ThenForEach(x => x.Products.ForEach(y => y.SupplierID =  x.SupplierID)).ThenBulkMerge(x => x.Products);
}

// STEP BULKDELETE
using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
    connection.BulkDelete(suppliers.SelectMany(x => x.Products)).BulkDelete(suppliers);
}

4. 總結

這些外掛讓Dapper更強,也更具備一個完整的ORM的方法,當然實際開發中需要結合實際需求使用。可能並不是所有的都合適。

Dapper的內容就到此為止了。本來預計下一篇開始 asp.net core的內容,不過有個小夥伴推薦了FreeSql,我看了下感覺挺不錯的,就給小夥伴們介紹一下~這一個介紹完成之後,就進入了我期待已久的asp.net core系列了。

更多內容煩請關注我的部落格《高先生小屋》

file

相關文章