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来执行资料库语法以及资料库栏位跟类别属性的对应问题,希望对大家在资料库的处理可以快速开发。


<<:  【Day 21】Lambda 函式

>>:  Day21 用更高阶的网路框架实现更多功能

day17:First-class function

在了解 first-class 一等公民函式前,我们先来看看 MDN 对於 first class ...

D23: 工程师太师了: 第12话

工程师太师了: 第12话 杂记: 今天看到一个议题 到底对自己做长远的规划是否比较好? 很多人都会对...

[Day15] Server - 中场来点 NGINX 设定

没错就是这麽突然~要开始设定 server 。主要是因为我们开发完後,会需要一个网站来放我们APP官...

不玩惹把钱还给我好否 - 抽单

今晚的美股又跳水惹 假如我们预计要挂个价格出去但发现价格不如预期的往反方向走,该怎麽办呢? 当然是赶...

Day9:今天来聊一下Parrot Security的Nmap

Nmap是一款用於网路发现和安全稽核网路安全工具,Nmap是Network Mapper的简称 Nm...