ユーザーアカウントデータベースは、エンティティ属性値(EAV)スキーマの最適な候補です。
これは通常、十分に小さく(1つのEAVの弱点、つまりパフォーマンス/スケーリングに関する懸念はありません)、ユーザーアカウントの構成は通常、パッケージ化とルールの終わりのない変更の対象となります。別
の方法として、オブジェクトデータベースを使用することもできます。これにより、以下で説明するモデルのオブジェクトインスタンスがストレージに「休止」されます。この後者のアプローチの欠点は、アカウントデータベース全体を操作することがより困難になる可能性があることです。確かに、悪い選択は、(質問で示唆されているように)真にリレーショナルなスキーマであり、そのレコードがアプリケーションレベルに直接公開されることは少なくなります。
一言で言えばEAV
データは「水平」ではなく「垂直」に保存されます。質問の例では、顧客ID 1の場合、値テーブルに4つのレコードがあり、それぞれが説明、montly_price、max_users、およびmax_customers用です。より多くの属性が必要な場合(たとえば、高度な/プレミアム機能へのアクセスを提供することを目的としたもの)、それらの一部に複数の値が含まれている可能性がある場合は、属性テーブルでそれらを定義し、同じテーブルに値レコードを追加します。
詳細:
データベース構造は通常、次の3つのテーブルで構成されます。
- tblEntity(ここではTblAccountと呼びます)。エンティティ(アカウント)ごとに1つの行があります。特定のアカウントに共通の情報を保持します:AccountId、Name、多分Login / pawsord、多分有効期限ですが、一般的にはほとんどありません。
- tblAttribute属性の定義を保持します:AttributeId、Name、Type
- 前に示唆したように、特定のエンティティ(アカウント)に割り当てられた属性値ごとに1つのレコードを持つtblValues
プログラムロジックとの連携:
通常、アカウントが少数の「ヘッダー」プロパティ(Id、name)にすぎず、さまざまな属性がハッシュ(辞書)のキーと値のペアに格納されるオブジェクトモデルを導入します。これらのオブジェクト、またはいくつかのユーティリティメソッドは、アカウントに関するすべての問い合わせとアクションを処理するためのレイヤーを提供します。例:
-bool CanUserAccess(FeatureName); // FeatureNameに関連付けられたルール(通常、そのアカウントの属性の存在や値に関する一連のテスト)を評価し、アカウントがその機能に事前にアクセスできる場合はtrueを返します(別のレイヤーが特定の時間にそのようなアクセスを防ぐ可能性があります) 、同時ユーザー数またはその他のため...)
-int TakeLicenseFor(FeatureName);
-など。
そしてそれは一般的にそれをカバーしています。多くの詳細はまだ解明されていませんが、上記で提案された暫定的なアーキテクチャは、パズルのさまざまな要素の全体的な緩い結合を提供します。
- データベースは、SQLのスキーマを変更せずに、アプリケーションレベルのスキーマ(主に属性テーブル)を変更するだけで、すぐに新しい属性を受け入れることができます。
- データベースは、ログイン時に、アカウントを表すオブジェクトをロードするために使用されます
- アプリケーションは、アプリケーションの機能(必要に応じてセグメント)を指定するために記号名(文字列)を使用し、ビジネスルールレイヤーを介して基になるアカウントでそのような機能が利用できるかどうかを問い合わせます(アカウント属性と機能:アカウントを変更せずに、1つまたは複数のアカウント属性にマップできる場合は、一部の機能を追加または削除できます。
2層の断熱材を使用しているため、データベースの物理的なレイアウトが変更されたり、ビジネスルールが変更されたりしても、アプリケーションに問題は発生しません。もちろん、アプリケーションには結びつきがあります。これらの「機能文字列」への参照ですが、これらの参照は通常、スクリプトの上位(初期)に配置できるため、アプリケーションのページ/機能間の非常に見やすく、簡単に変更できるマッピングが可能になります。およびアカウント管理ロジックについて説明します。