Skip to content

パラメータの差分を DB に持つ ​

第1版作成 最終更新 (日本時間)
確認バージョン1.5.1.01.5.8.1

本体の標準機能ではありません

このページは、パラメータを差分の JSON だけで持つ の案 A(C# の既定値 + 変更した項目だけの JSON)を前提に、その JSON を DB にも持てるようにする設計メモです。

複数の Web サーバーへの即時反映、画面からの設定変更、テナントごとのパラメータ、DB のバックアップへのパラメータの同梱、変更履歴の追跡を目的にします。

前提にした 1.5.8.1 の実装 ​

  • パラメータはファイル(App_Data/Parameters/*.json)から読み込みます。Rds の接続文字列だけは、空なら環境変数から補います(パラメータ の「読み込みのしくみ」)。
  • 1.5.8.1 にはすでに Parameters テーブル(ParameterId(IDENTITY の主キー)・Title・Body)があり、EnableScreenManagement を有効にすると、特権ユーザーが画面で変えた項目の差分(op・path・value の配列)を Title = パラメータ名で保存します。起動時と再読み込みのときに、ファイルから読んだ値にこの差分を当てます(Initializer.cs#L364-L469)。
  • 既存の仕組みは、土台がファイルの全項目であること、テナントの区別が無いこと(Title だけで引く)、Rds・Env・ParameterSetting・Migration などは対象外であることが、このページの設計と違います。以下は、既存の Parameters テーブルを拡張するか、別のテーブルを作るかを含めて検討するためのメモです。

Rds はファイルから読むしかない ​

Rds.json には DB の接続文字列が入っているため、DB から読むことはできません(DB に接続するための情報を DB に置けない)。読み込み元は次の 2 つに分けます。

分類パラメータ読み込み元
ファイルだけRds(と DB に接続する前に要る Env など)環境変数 → ファイル → C# の既定値
ファイルと DBApi・Security・General・Mail など環境変数 → DB(テナント)→ DB(全体)→ ファイル → C# の既定値

テーブル ​

差分の JSON を持つテーブル ParameterSources を、プリザンターの標準の形(本体・_deleted・_history の 3 テーブル)で作ります。CodeDefiner の Definition_Column/ に ParameterSources_*.json を足せば、テーブルは CodeDefiner が作ります(CodeDefiner の「対象のテーブル」)。

列型NULL内容
TenantIdint不可テナント ID。0 は全テナント共通
ParameterNamenvarchar(128)不可パラメータ名(C# のクラス名。Api など)
Bodynvarchar(max)可変更した項目だけの JSON。NULL なら C# の既定値だけ
Verint不可版。更新のたびに増やし、楽観的排他に使う
Commentsnvarchar(max)可変更理由などのコメント(JSON の配列)
Creator / Updatorint不可作成者・更新者の UserId
CreatedTime / UpdatedTimedatetime不可作成・更新日時

主キーは (TenantId, ParameterName)、_history は (TenantId, ParameterName, Ver) です。

TenantId = 0 を全体の設定に使える理由 ​

Tenants の TenantId は IDENTITY で Seed が 1 です。CodeDefiner は Seed が 0 でも 1 にして IDENTITY を作るため、SQL Server(identity(1, 1))・PostgreSQL(start with 1)・MySQL(auto_increment = 1)のどれでも、通常の運用で TenantId = 0 のテナントはできません(Tenants_TenantId.json、Columns.cs#L156-L159)。現行のファイルはテナントの区別の無い全体の設定なので、TenantId = 0 がそれに当たります。外部キー制約は付けません。

読み込み ​

図を読み込み中…

Read<T>() に「DB を使うか」の引数を足し、Rds などは DB を使わずに読みます。

csharp
private static T Read<T>(bool required = true, bool dbAvailable = true) where T : new()
{
    var name = typeof(T).Name;
    string json = dbAvailable ? ReadFromDb(name, tenantId: 0) : null;
    if (json.IsNullOrEmpty()) json = Files.Read(JsonFilePath(name));
    if (!json.IsNullOrEmpty())
    {
        var data = json.Deserialize<T>();
        if (data == null && required)
            throw new ParametersIllegalSyntaxException(name + ".json");
        return data ?? new T();
    }
    if (required) throw new ParametersNotFoundException(name + ".json");
    return new T();
}

private static string ReadFromDb(string parameterName, int tenantId)
{
    try
    {
        // TenantId が tenantId か 0 の行を、TenantId の大きい順に 1 件
        return /* select top 1 "Body" from "ParameterSources" ... */;
    }
    catch
    {
        return null; // テーブルが無い(初回)・DB に接続できないときはファイルへ
    }
}
  • DB とファイルの両方にあるときは、DB だけを使います(2 つの差分を重ねない)。どちらが使われたかが分かりやすく、DB に移したあとはファイルを消す運用にします。
  • 初回の起動ではテーブルがまだ無いので、ReadFromDb() は例外を握って null を返し、ファイルと既定値で動きます。CodeDefiner でテーブルを作ったあとの起動から DB を読みます。
  • 環境変数は従来どおり最優先で、DB やファイルで読んだあとに項目ごとに上書きします。
  • 配列の項目は、差分の JSON に書くと配列ごと置き換わります(部分的な追加・削除はできません)。
  • 本文が JSON として読めなければ ParametersIllegalSyntaxException にします。

書き込みと移行 ​

書き込み口は、将来のパラメータ編集画面、管理用の API、CodeDefiner のコマンド、運用者の SQL を想定します。SQL Server なら MERGE で Ver を増やしながら UPSERT します。

移行は段階的に行います。

段階内容既存環境への影響
1Read<T>() を DB → ファイル → 既定値の順に読む形にするなし(DB に行が無ければ従来どおり)
2param-import コマンド(新規)でファイルの JSON を DB に取り込む(Rds.json は飛ばす)なし
3取り込んだファイルを消す(任意。残しても DB が優先)なし

param-export コマンドで DB の JSON をファイルに書き戻せるようにしておけば、いつでもファイルの運用に戻せます。

テナントごとのパラメータ(将来) ​

TenantId > 0 の行を足せば、テナントごとに違うパラメータを使えます。リクエストのテナントの行が無ければ TenantId = 0 の行、それも無ければファイル・既定値の順です。

区分例
テナントごとに変える意味があるものApi(PageSize など)、Security(ロックアウトの回数など)、General(一覧の件数など)
テナントごとに変えるべきでないものRds(不可能)、BinaryStorage(保存先)、Service(サービス名)などの基盤の設定

テナントごとの値はリクエストのたびに DB から読まず、キャッシュする仕組みが要ります。テナントの設定を読み込む Context.SetTenantProperties と同じタイミングで読み込むことが考えられます。

関連ページ ​

変更履歴

第1版CodeDefiner のデータベース作成・更新とパラメータの引き継ぎ、画面でのパラメータ管理、MCP エンドポイントのブラウザアクセスの解説と、関連する改修・設計メモを追加