質問: 私に「モデル」エンティティのセットと難易度のセットがあるとします。各モデルは、与えられた難易度である日の一定の成功率を示します。 モデル実体には名前はありますが、名前は一意であり、いかなる状況下でも不変であるため、自然な主キーとなります。難易度レベルはその名前だけで記述されます(簡単、普通など)。難易度レベルは非常に変わることはほとんどありませんが、新しいレベルを追加することは可能です。成功率記録は、それが関係するモデル、難易度、および日付によって一意に識別される。 このシナリオで最も簡単なDBデザインは次のとおりです。 !ナチュラルキーによるdbデザイン この設計では、 'name'は表 'モデル'の主キーであり、VARCHAR(20)フィールドで表されます。同様に、VARCHAR(20)フィールド 'name'はテーブル 'difficult_levels'(ルックアップテーブル)の主キーです。 'success_rates'テーブルで 'model_name'は 'model'テーブルの 'name'フィールドを参照する外部キーで、 'difficult_level'は 'difficult_levels'テーブルの 'name'フィールドを参照する外部キーです。 'model_name'、 'difficult_level'、 'date'の各フィールドは、 'success_rates'テーブルの複合主キーを構成します。 最もよく使用されるクエリは次のとおりです。 * 特定のモデル、難易度、日付期間のすべての成功率を得る * 特定の期間と難易度のために最も成功したモデルまたは最も成功しなかったモデルを得る。 今、私の質問は - 私は 'models'と 'difficult_levels'テーブルに代理プライマリキーを追加する必要がありますか?私は、 'success_rates'の外部キーフィールドにvarchar値を格納するのではなく、int値を格納することが少ないスペースを占有し、おそらくクエリが高速になります(私の野生の推測、それについてはわかりません)? サロゲートキーで見られる問題は、ビジネスロジック自体との関連性がゼロであることです。私はミニORM(ほとんどの場合、Dapper)を使用することを計画しています。代理キーがなければ、私が扱っているエンティティを非常にきれいに表すクラスで操作できます。今、代理キーを追加すると、クラスに 'Id'プロパティを追加する必要があります。そのようなデータベースストレージの実装を、アプリ内のどこでも使用できるクラスに追加することには本当に反対です。データベースストレージとの接続。私はIdプロパティを持つプロキシストレージクラスを追加することができましたが、それは別のレベルの複雑さを追加します。さらに、 'Id'プロパティが読み込み専用ではないという事実(ORMはエンティティをデータベースに保存した後にidを設定できる)は、誤ってランダム/無効な値に設定する可能性があることを意味します。 私はORMのことにあまり慣れていないし、私はDapperの知識もないので、これらの点のいずれかが間違っていたら私を修正してください。 ここで最善のアプローチは何でしょうか?
回答: > > > サロゲートキーで見られる問題は、ビジネスロジック自体との関連性がゼロであることです。 > > > > > > それは実際には利益であり、問題ではありません。キーの値は、それ以外の変更にかかわらず、エンティティの不変の識別子です。私は本当にそれを使いこなすことができない広く使われているORMがあることを本当に疑っています。代替(すべての子レコードへの重要な価値へのカスケード変更)は実装するのがはるかに難しいためです。 また、難易度の高い階層をデータモデルで表現できる難易度レベルに値を追加することをお勧めします。そうでなければ、「より難しい」または「より簡単」を堅実に表現することはできません。