D-09 資料庫存取 ? Dapper

怎麼處理資料庫溝通

相信這點是每個程式開發工程師關注的點,在dotnetcore中可以選擇EntityFramework或是用ADO.NET來處理資料庫問題,不過今天要介紹的是羽量級的套件Dapper,請大家繼續看下去。

如何處理資料庫溝通

「前輩,我要開始搞資料庫了,我該從哪裡著手」
一早大頭又有需求上的問題,今天似乎是跟資料庫相關的問題,由於小光也曾經有類似的問題,所以也想暸解該如何處理。
「那你有什麼需求呢?」
老K聽到大頭的問題之後反問他這個問題,這時大頭歪了頭想了一下,就這麼說。
「我想要寫一個處理速度快又可以簡單寫的」
聽到這回答後換老K思考了幾分鐘後這麼說。
「那你跟小光去研究一下Dapper」

Dapper

Dapper是一個針對關聯是資料表來處理效能優化的套件,而且使用上也不像ADO.NET要經過繁瑣的動作才可以解析資料庫的資料,而且使用上相當簡單,不過在進入教學前先來看一下環境設定的部分。

環境設定

首先要安裝的套件如下列命令列。

dotnet add package Dapper
dotnet add package System.Data.SqlClient

這邊說明一下,上面是安裝Dapper而下面安裝的是MsSql的連接程式,所以之後先說明如何跟MsSql連線。

連線處理

這邊我們是透過DbProviderFactories來取得對應的連線工具,以目前例子來說對於MsSql就是要指定System.Data.SqlClient

var providerFactory = DbProviderFactories.GetFactory(ProviderName);
var connection = providerFactory.CreateConnection();
if (connection != null)
{
    connection.ConnectionString = connectionString;
}

return connection;

不過並不是這樣就可以了,我們必須在程式開始前先註冊才行,所以在Program.Main執行以下動作。

DbProviderFactories.RegisterFactory("System.Data.SqlClient", System.Data.SqlClient.SqlClientFactory.Instance);

接下來要注意的是,使用連線串的語句時要用using把他包起來,簡單講就是做完查詢後要釋放掉,這樣MsSql的連線才會透過連線池的管理,詳細的資訊可以看一下這篇[SQL Connection Pooling 行為觀察]。

using (var connection = await GetConnection("連線串"))
{
    var sql = @"SELECT GETUTCDATE()";
    result = await connection.QueryFirstOrDefaultAsync<DateTime>(sql);
}

至於連線串的部分可以透過之前介紹的設定檔來取的即可。

執行語法

其上在上面的範例種已經看到執行語法了,只要熟悉Linq的語句應該就如何使用了,再來就是後贅詞有Async指的就是非同步的方法,所以如果要等待完成的話前面要記的加上await,最後泛型的部分就是要轉型成甚麼類別。
如果有需要傳入參數的話就透過以下方式來傳遞。

public class Dog
{
    public int? Age { get; set; }
    public Guid Id { get; set; }
    public string Name { get; set; }
    public float? Weight { get; set; }

    public int IgnoredProperty { get { return 1; } }
}

var guid = Guid.NewGuid();
var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });

不過這邊要注意一下關於使用到指定長度的字串,Dapper的執行會影響執行計畫,詳細請看這篇Dapper 用起來很友善,但是預設的參數型別對執行計劃不太友善。,所以在輸入字串時要注意輸入的值跟資料庫定義的值一致,如下所示。

await connection.QueryFirstOrDefaultAsync<PlayInfo>(sql,
new
{
    Name = new DbString { Value = name, Length = 32 }
}

簡單說明就是使用DbString這類別即可,至於細部資訊請看前面那一篇。

欄位對應

當然類別的屬性名稱未必會跟資料庫的欄位相符,所以這邊可以透過以下方法來將屬性名稱對應到資料庫欄位,首先先安裝以下套件Dapper.FluentMap

dotnet add package Dapper.FluentMap

接下來建立對應的類別。

public class ProductMap : EntityMap<Product>
{
    public ProductMap()
    {
        // Map property 'Name' to column 'strName'.
        Map(p => p.Name)
            .ToColumn("strName");

        // Ignore the 'LastModified' property when mapping.
        Map(p => p.LastModified)
            .Ignore();
    }
}

如果這邊不在乎欄位大小寫的話可以用以下語法。

Map(p => p.Name).ToColumn("strName", caseSensitive: false)

建立好對應的類別後再將他註冊進去即可,註冊的方法要在Startup.ConfigureServices加上以下語法即可。

FluentMapper.Initialize(cfg =>
{
    cfg.AddMap(new ProductMap());
});

後記

今天跟小光還有大頭認識如何處理連線問題,已經如何使用Dapper來執行資料庫語法以及資料庫欄位跟類別屬性的對應問題,希望對大家在資料庫的處理可以快速開發。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *