扩展-数据库种类

ClownFish只支持几种常用数据库,如果没有你需要的数据库,请自行扩展。

本文演示对 人大金仓-KingbaseES 数据库的支持


引用数据库驱动包

首先我们引用官方的客户端驱动

<ItemGroup>
    <PackageReference Include="Kdbndp_V9" Version="8.0.1.906" />
</ItemGroup>



实现 BaseClientProvider 抽象类

完整代码如下:

public class KingbaseESClientProvider : BaseClientProvider
{
    public static readonly BaseClientProvider Instance = new KingbaseESClientProvider();

    #region 定义2个"常量",可以避免在其它代码中出现“硬编码”。
    public static readonly string ProviderName = "Kdbndp";

    // 由于 DatabaseType 是枚举,无法扩展,所以只能使用“强转”方式
    public static readonly DatabaseType DatabaseTypeKingbaseES = (DatabaseType)7777;
    #endregion


    public static void RegisterProvider()
    {
        // Npgsql 6.0 对时间戳的映射方式进行了一些重要更改
        // https://www.npgsql.org/doc/types/datetime.html#timestamps-and-timezones
        AppContext.SetSwitch("Kdbndp.EnableLegacyTimestampBehavior", true);
        AppContext.SetSwitch("Kdbndp.DisableDateTimeInfinityConversions", true);

        DbClientFactory.RegisterProvider(ProviderName, Instance);
    }

    public override DatabaseType DatabaseType => DatabaseTypeKingbaseES;

    public override DbProviderFactory ProviderFactory => Kdbndp.KdbndpFactory.Instance;

    public override string GetObjectFullName(string symbol)
    {
        // https://help.kingbase.com.cn/v8/faq/faq-new/sql.html#id12
        return "\"" + symbol + "\"";
    }


    public override CPQuery GetNewIdQuery(CPQuery query, object entity)
    {
        return query + "; SELECT lastval();";  // 参考 PostgreSql 的实现
    }


    public override bool IsDuplicateInsertException(Exception ex)
    {
        if( ex is Kdbndp.KingbaseException ex2 ) {
            return ex2.SqlState == "23505";  // 参考 PostgreSql 的实现
        }

        return false;
    }


    public override CPQuery SetPagedQuery(CPQuery query, int skip, int take)
    {
        return StdClientProvider.SetPagedQuery(query, skip, take);
    }

    public override Page2Query GetPagedCommand(BaseCommand query, PagingInfo pagingInfo)
    {
        return StdClientProvider.GetPagedCommand(query, pagingInfo);
    }

    public override string GetConnectionString(IDbConfig dbConfig, bool includeDatabase)
    {
        return PostgreSqlClientProvider.GetPostgreSQLConnectionString0(dbConfig, includeDatabase);
    }
}



初始化

在程序启动过程中,

ClownFishInit.InitDAL();

// 在 InitDAL 之后调用
KingbaseESClientProvider.RegisterProvider();



配置连接

<configuration>
    <connectionStrings>
        <add name="kingbase2" providerName="Kdbndp"
            connectionString="Host=192.168.1.1;database=mynorthwind;port=34321;Username=sa;Password=xxxxxxx"/>
    </connectionStrings>

    <dbConfigs>
        <add name="kingbase3" dbType="7777" server="192.168.1.1" port="34321" database="mynorthwind" uid="sa" pwd="xxxxxxx" args="" />
    </dbConfigs>
</configuration>

说明:

  • 连接名“kingbase2”,设置了 providerName="Kdbndp"
    • 这是调用 DbClientFactory.RegisterProvider方法的第一个参数
  • 连接名“kingbase3”,设置了 dbType="7777"
    • 它是 KingbaseESClientProvider.DatabaseType 的返回结果



测试代码

using( DbContext db = DbContext.Create("kingbase2") ) {

    // 确认此DbContext实例将会使用 KingbaseESClientProvider
    Assert.AreEqual(KingbaseESClientProvider.DatabaseTypeKingbaseES, db.DatabaseType);
    Assert.AreEqual(KingbaseESClientProvider.ProviderName, db.ProviderName);        
    
    long id = db.CPQuery.Create("select max(productid) from products").ExecuteScalar<long>();
    Assert.IsTrue(id > 0);
}


using( DbContext db = DbContext.Create("kingbase3") ) {

    Assert.AreEqual(KingbaseESClientProvider.DatabaseTypeKingbaseES, db.DatabaseType);
    Assert.AreEqual(KingbaseESClientProvider.ProviderName, db.ProviderName);

    long id = db.CPQuery.Create("select max(productid) from products").ExecuteScalar<long>();
    Assert.IsTrue(id > 0);
}