讓Dapper在一個專案中支援多種庫

語言: CN / TW / HK

如果想在一個專案中,用DapperPlus支援多種資料庫該怎麼做?

在《 讓Dapper支援Mock 》中我們定義了DapperPlus,可以基於這個類,實現兩個子類:MySqlDapperPlus,MsSqlDapperPls,在這兩個子類的構造中適配對應的資料庫型別,從注放容器中,獲取IDbConnection例項,根據例項的型別來選取配置中的對應連線字串,這裡用到的是根據資料型別來配置,也是一種約定。

MySqlDapperPlus.cs

using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;


namespace WebDemo01.Services
{
public class MySqlDapperPlus : DapperPlus
{
public MySqlDapperPlus(IEnumerable<IDbConnection> connections, IConfiguration configuration)
{
var connectionStrings = configuration.GetSection("ConnectionStrings").Get<Dictionary<string, string>>();
_connection = connections.FirstOrDefault(c => c.GetType().Name == "MySqlConnection");
_connection.ConnectionString = connectionStrings.Where(s => s.Key.ToLower().Contains("mysql")).FirstOrDefault().Value;
}
}
}

MsSqlDapperPlus.cs

using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;


namespace WebDemo01.Services
{
public class MsSqlDapperPlus : DapperPlus
{
public MsSqlDapperPlus(IEnumerable<IDbConnection> connections, IConfiguration configuration)
{
var connectionStrings = configuration.GetSection("ConnectionStrings").Get<Dictionary<string, string>>();
_connection = connections.FirstOrDefault(c => c.GetType().Name == "SqlConnection");
_connection.ConnectionString = connectionStrings.Where(s => s.Key.ToLower().Contains("mssql")).FirstOrDefault().Value;
}
}
}

這時,會有問題,DapperPlus沒有無參構造,_connection訪問級別也太低,所以要改造一下DapperPlus。

    /// <summary>
/// DappePlusr類
/// </summary>
public class DapperPlus : IDapperPlus
{
protected IDbConnection _connection;
/// <summary>
/// 無參建構函式
/// </summary>
public DapperPlus()
{
}
//下面和原來的一樣
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();

services.AddScoped<IDbConnection, MySqlConnection>();
services.AddScoped<IDbConnection, SqlConnection>();
services.AddScoped<IDapperPlus, MySqlDapperPlus>();
services.AddScoped<IDapperPlus, MsSqlDapperPlus>();
}

appsettings.json

  "ConnectionStrings": {
"MySqlConnectionString": "server=127.0.0.1;uid=root;pwd=root;database=mysql_testdb",
"MsSqlConnectionString": "server=127.0.0.1;uid=root;pwd=root;database=mssql_testdb"
}

如果是多個庫,還要讀寫分離該怎麼實現? 其實和不分離是一樣的,要改造《 讓Dapper讀寫分離 》中的DapperPlusWrite和DapperPlusRead兩個類,分別增加無參建構函式,和把_connection改成protected,方便子類中參訪問到。

然後定義三個類:MySqlDapperPlusRead和MsSqlDapperPlusRead繼承DapperPlusRead;MySqlDapperPlusWrite和MsSqlDapperPlusWrite繼承DapperPlusWrite。在四個類的建構函式中,按照自己資料庫的型別,Read或Write型別來取配置檔案中的連線字串即可。

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddScoped<IDbConnection, MySqlConnection>();
services.AddScoped<IDbConnection, SqlConnection>();
services.AddScoped<IDapperPlusRead, MySqlDapperPlusRead>();
services.AddScoped<IDapperPlusRead, MsSqlDapperPlusRead>();
services.AddScoped<IDapperPlusWrite, MySqlDapperPlusWrite>();
services.AddScoped<IDapperPlusWrite, MsSqlDapperPlusWrite>();
}

appsettings.json

  "ConnectionStrings": {
"MySqlReadConnectionString": "server=127.0.0.1;uid=root;pwd=root;database=read_mysql_testdb",
"MySqlWriteConnectionString": "server=127.0.0.1;uid=root;pwd=root;database=write_mysql_testdb",
"MsSqlReadConnectionString": "server=127.0.0.1;uid=root;pwd=root;database=read_mssql_testdb",
"MsSqlWriteConnectionString": "server=127.0.0.1;uid=root;pwd=root;database=write_mssql_testdb"
}

最後,在業務的Service中,讀有兩個,按型別區分,寫有兩個,按型別區分,程式碼如下:

    public class GoodsService : IGoodsService
{
private readonly IDapperPlusWrite _mySqlDapperWrite;
private readonly IDapperPlusWrite _msSqlDapperWrite;
private readonly IDapperPlusRead _mySqlDapperRead;
private readonly IDapperPlusRead _msSqlDapperRead;
public ShopService(IEnumerable<IDapperPlusWrite> dapperWrites, IEnumerable<IDapperPlusRead> dapperReads)
{
foreach (var dapperWrite in dapperWrites)
{
switch (dapperWrite)
{
case MySqlDapperPlusWrite mySqlDapperPlusWrite:
_mySqlDapperWrite = mySqlDapperPlusWrite;
break;
case MsSqlDapperPlusWrite msSqlDapperPlusWrite:
_msSqlDapperWrite = msSqlDapperPlusWrite;
break;
}
}
foreach (var dapperRead in dapperReads)
{
switch (dapperRead)
{
case MySqlDapperPlusRead mySqlDapperPlusRead:
_mySqlDapperRead = mySqlDapperPlusRead;
break;
case MsSqlDapperPlusRead msSqlDapperPlusRead:
_msSqlDapperRead = msSqlDapperPlusRead;
break;
}


}
}
}

往期 精彩 回顧

【推薦】.NET Core開發實戰視訊課程   ★★★

.NET Core實戰專案之CMS 第一章 入門篇-開篇及總體規劃

【.NET Core微服務實戰-統一身份認證】開篇及目錄索引

Redis基本使用及百億資料量中的使用技巧分享(附視訊地址及觀看指南)

.NET Core中的一個介面多種實現的依賴注入與動態選擇看這篇就夠了

10個小技巧助您寫出高效能的ASP.NET Core程式碼

用abp vNext快速開發Quartz.NET定時任務管理介面

在ASP.NET Core中建立基於Quartz.NET託管服務輕鬆實現作業排程

現身說法:實際業務出發分析百億資料量下的多表查詢優化

關於C#非同步程式設計你應該瞭解的幾點建議

C#非同步程式設計看這篇就夠了