7

SaaS コンセプトのマルチテナンシー データベース スキーマ設計を検討しています。ASP.NET MVC -> EF になりますが、それはそれほど重要ではありません。

以下に、データベース スキーマの例を示します (テナントは会社です)。CompanyId はスキーマ全体で複製され、主キーは自然キーとテナント ID の両方に配置されています。

このスキーマを Entity Framework にプラグインすると、テーブルを Entity Model ファイル (Model1.edmx) に追加すると、次のエラーが発生します。

  • リレーションシップ 'FK_Order_Customer' は、テーブル 'Order' の主キー '{OrderId, CompanyId}' のセットに部分的に含まれている外部キー '{CustomerId, CompanyId}' のセットを使用します。外部キーのセットは、主キーのセットに完全に含まれているか、モデルにマップされる主キーのセットに完全に含まれていない必要があります。
  • 関係 'FK_OrderLine_Customer' は、テーブル 'OrderLine' の主キー '{OrderLineId, CompanyId}' のセットに部分的に含まれている外部キー '{CustomerId, CompanyId}' のセットを使用します。外部キーのセットは、主キーのセットに完全に含まれているか、モデルにマップされる主キーのセットに完全に含まれていない必要があります。
  • 関係 'FK_OrderLine_Order' は、テーブル 'OrderLine' の主キー '{OrderLineId, CompanyId}' のセットに部分的に含まれている外部キー '{OrderId, CompanyId}' のセットを使用します。外部キーのセットは、主キーのセットに完全に含まれているか、モデルにマップされる主キーのセットに完全に含まれていない必要があります。
  • リレーションシップ 'FK_Order_Customer' は、テーブル 'Order' の主キー '{OrderId, CompanyId}' のセットに部分的に含まれている外部キー '{CustomerId, CompanyId}' のセットを使用します。外部キーのセットは、主キーのセットに完全に含まれているか、モデルにマップされる主キーのセットに完全に含まれていない必要があります。
  • 関係 'FK_OrderLine_Customer' は、テーブル 'OrderLine' の主キー '{OrderLineId, CompanyId}' のセットに部分的に含まれている外部キー '{CustomerId, CompanyId}' のセットを使用します。外部キーのセットは、主キーのセットに完全に含まれているか、モデルにマップされる主キーのセットに完全に含まれていない必要があります。
  • 関係 'FK_OrderLine_Order' は、テーブル 'OrderLine' の主キー '{OrderLineId, CompanyId}' のセットに部分的に含まれている外部キー '{OrderId, CompanyId}' のセットを使用します。外部キーのセットは、主キーのセットに完全に含まれているか、モデルにマップされる主キーのセットに完全に含まれていない必要があります。
  • リレーションシップ 'FK_OrderLine_Product' は、テーブル 'OrderLine' の主キー '{OrderLineId, CompanyId}' のセットに部分的に含まれている外部キー '{ProductId, CompanyId}' のセットを使用します。外部キーのセットは、主キーのセットに完全に含まれているか、モデルにマップされる主キーのセットに完全に含まれていない必要があります。

質問は 2 つの部分に分かれています。

  1. 私のデータベース設計は間違っていますか? これらの複合主キーは控えるべきですか? 私は、基本的なスキーマ設計 (frazzled Brain Syndrome) に関する私の正気を疑っています。「理想化された」スキーマを提案してください。
  2. あるいは、データベースの設計が正しい場合、EF はこれらの外部キーを 1 対 1 の関係が誤って構成されている可能性があると認識しているため、キーを照合できませんか? どの場合、これは EF のバグですか?どうすれば回避できますか?

マルチテナンシー データベース スキーマ

4

5 に答える 5

4

EF のエラー メッセージをざっと見てみると、複合キーの設定方法が気に入らないことが明らかであり、おそらく正しい方向に進んでいると思います。主キーが一意である理由をもう一度考えてみてください。CompanyID がなければ、OrderID だけでは一意ではありませんか? CompanyID がなければ、ProductID は一意ではありませんか? OrderLine は単一の Order にのみ関連付けられる必要があるため、CompanyID がなくても OrderLine は一意である必要があります。

これらすべてに本当に CompanyID が必要な場合、つまり問題の会社が ProductID と OrderID を提供していることを意味する場合は、別の方向に進み、データに固有ではない独自の主キーを生成することをお勧めします。 . 主キーの自動インクリメント列を設定し、これらを内部の OrderID、OrderLineID、ProductID、CompanyID などにします。その時点で、OrderLine は顧客の OrderID または CompanyID を必要としません。Order への外部キー参照がその開始点になります。(また、CustomerID は注文明細行の属性であってはなりません。注文明細行ではなく、注文の属性です。)

複合キーは面倒です。それらなしでモデルを設計してみて、物事が単純化されるかどうかを確認してください。

于 2010-05-30T12:43:06.110 に答える
3

設計に誤りはないと思います。EF にはありません。 Sql Server 関係にあります。

EF メッセージを読みます。

リレーションシップ 'FK_Order_Customer' は、テーブル 'Order' の主キー '{OrderId, CompanyId}' のセットに部分的に含まれている外部キー '{CustomerId, CompanyId}' のセットを使用します。外部キーのセットは、主キーのセットに完全に含まれているか、モデルにマップされる主キーのセットに完全に含まれていない必要があります。

エラー

実際には、Order と Customer の間の関係は 1 つのフィールドのみを使用します (おそらく、Order テーブルのフィールド「CustomerId」を Customer テーブルの「Id」にマウスでドラッグしました)。

解決

Order と Customer を接続するワイヤを右クリックし、関係に CompanyId も追加します。


PS: デザインは正しいです。

各テーブルに CompanyId を配置することは、スケーリングに役立つため、マルチテナント アーキテクチャの優れたソリューションです (通常は常に、loggedIn の会社からレコードのみを選択する必要があります)。

于 2010-11-12T09:16:04.920 に答える
2

会社番号を各テーブルに保存することは、あなたを助けるよりも傷つけていると思います。あなたがこれをやりたい理由は理解できます (プログラマー/データベース管理者として、任意のテーブルに移動して、どのデータが誰のものであるかを「見る」ことができます)。あるべき姿。

複合キーを避けると、デザインがずっとシンプルになります。

于 2010-05-30T13:19:31.180 に答える
0

まず、他の人が言ったように、外部キーを参照するときは、他のテーブルの主キー全体 (つまり、両方のフィールド) を使用します。

第二に、深刻なアプリケーションのほとんどのテーブルで CompanyID 列を使用しないとは考えられません。この場合、 Orderdetail はおそらく例外かもしれません (テナントに依存しない限り、おそらくグローバル ルックアップ テーブルも同様です)。つまり、その列を持つテーブルに到達するまで、CompanyID を追加するか、JOIN を実行しない限り、テーブルに対して安全な種類の自由形式検索を実行することはできません。後者は明らかにパフォーマンスを犠牲にします。おそらくこの場合、orderdetail の例外を作成し、結合されたバージョン (2 つのテーブルのみ) のみを検索できます。繰り返しますが、実際には一貫していません。

また、それを複合キーにするかどうかについて: 可能ですが、バグの期間中、バグが情報を誤って (存在しない、または他の人の管理に) 書き込む可能性があります。システムで競合他社の注文が表示される理由を顧客に説明することは言うまでもなく、本番環境でそれを修正するようにしてください。

于 2013-10-26T00:28:27.923 に答える
0

各テーブルに CompanyID 列を絶対に追加する必要がある場合は、複合キーではなく通常の列として追加します。複合キーは、多対多の関係を実装する必要がある場合に主に使用されます。

誰かが言及したように、CompanyID に非クラスター化インデックスも作成して、Company テーブルへの結合にメリットがあります。

ありがとう!

于 2013-08-26T12:12:14.460 に答える