实例化 Database


  Database 是一个核心的实现,它实现了 IDatabase 接口定义的所有功能,它支持读写分离,所有的读操作都会使用从库,只有写操作才会使用主库,并自动开启事务。


1、Database 类

  Database类是 IDatabase 的默认实现,一般不建议直接使用 Database 类的构造函数来创建实例,但有必要介绍一下它的构造函数。如下所示:

[TestMethod]
public void TestDatabase()
{
    var connStr = "Data Source=localhost;database=northwind;User Id=root;password=faib;";
    using (var db = new Database(connStr, MySqlProvider.Instance))
    {
    }
}

  Database 类的构造函数接收一个数据库连接字符串,以及 IProvider 实例,一般使用 MsSqlProvider.Instance、MySqlProvider.Instance 等单例形式。

  Database 类除了接收一个数据库连接字符串,还可以接收一组数据库连接字符串,当数据库实例配置为集群模式时(见 数据库实例配置 -- 集群配置),使用的就是此构造函数。如下所示:

[TestMethod]
public void TestDistributedDatabase()
{
    var conStrs = new List<DistributedConnectionString> { 
        new DistributedConnectionString("Data Source=192.168.1.100;database=northwind;User Id=root;password=faib;") { Mode = DistributedMode.Master },
        new DistributedConnectionString("Data Source=192.168.1.101;database=northwind;User Id=root;password=faib;") { Mode = DistributedMode.Slave, Weight = 40 },
        new DistributedConnectionString("Data Source=192.168.1.102;database=northwind;User Id=root;password=faib;") { Mode = DistributedMode.Slave, Weight = 60 }
    };

    using (var db = new Database(conStrs, MySqlProvider.Instance))
    {
    }
}

2、使用 DatabaseFactory 创建

  DatabaseFactory 工厂类通过 数据库实例配置 来创建一个 IDatabase 实例。CreateDatabase 方法的 instanceName 参数和数据库实例配置中的 name 相对应,如果该参数,则使用默认的实例配置,即 default 项。如下所示:

[TestMethod]
public void TestCreateDatabase()
{
    var db1 = DatabaseFactory.CreateDatabase();
    var db2 = DatabaseFactory.CreateDatabase("mssql");
    Assert.IsNotNull(db1); // sqlite db;
    Assert.IsNotNull(db2); // sqlserver db;
}

  使用 CreateDatabase 创建的 IDatabase 实例类型是可以配置为自己定义的实现的,之前在数据库实例配置章节并没有提及,只需在配置项中通过指定 databaseType 为一个实现类即可。如下所示:

  • .Net Framework 下的 app.config 或 web.config 文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="fireasy">
      <section name="dataInstances" type="Fireasy.Data.Configuration.InstanceConfigurationSectionHandler, Fireasy.Data"/>
  </configSections>
  <fireasy>
    <dataInstances>
      <instance name="mysql"
        providerType="MySql"
        databaseType="demo.Database, demo",
        connectionString="Data Source=localhost;database=northwind;User Id=root;password=faib;pooling=true;charset=utf8"/>
    </dataInstances>
  </fireasy>
</configuration>
  • .Net Core 下的 appsettings.json 文件
{
  "fireasy": {
    "dataInstances": {
      "settings": {
        "mysql": {
          "providerType": "MySql",
          "databaseType": "demo.Database, demo"
          "connectionString": "Data Source=localhost;database=northwind;User Id=root;password=faib;pooling=true;charset=utf8"
        }
      }
    }
  }
}

3、从 Scope 里获取

  使用 DatabaseScope 类可以在同一线程范围内使用相同的一个 IDatabase 实例,DatabaseFactory 工厂类的 GetDatabaseFromScope 方法可以检索当前线程内是否有存在 DatabaseScope 实例,如果存在的话则返回 DatabaseScope 实例的 IDatabase 实例。如下所示:

[TestMethod]
public void TestScopedDatabase()
{
    using (var db = DatabaseFactory.CreateDatabase())
    using (var scope = new DatabaseScope(db))
    {
        TestFromScope();
    }
}

public void TestFromScope()
{
    using (var db = DatabaseFactory.GetDatabaseFromScope())
    {
        Assert.IsNotNull(db);
    }
}

  从 DatabaseScope 实例获得的 IDatabase 实例是一个 NoDisposeDatabase 类型的对象,它的 Dispose 方法不会执行资源释放。


4、ScopedDatabase 类

  ScopedDatabase 类继承自 Database 类,它在实例化时加入了一个 DatabaseScope 实例,因此如果使用此实例的话,是不需要在重新定义 DatabaseScope 实例的。如下所示:

[TestMethod]
public void TestScopedDatabase()
{
    var connStr = "Data Source=localhost;database=northwind;User Id=root;password=faib;";
    using (var db = new ScopedDatabase(connStr, MySqlProvider.Instance))
    {
        TestFromScope();
    }
}

public void TestFromScope()
{
    var db = DatabaseFactory.GetDatabaseFromScope();
    Assert.IsNotNull(db);
}