すべてのタグ割り当てに対して単一のテーブルを使用することに問題はありません (タグ付け可能なエンティティごとに 1 つの複数のテーブルとは対照的に)。
ただし、あなたのデザインの 1 つの重要な詳細は私にはあいまいなままです: これらの線に沿って何かを持っている場合
- - - - - - - - - -
Tag
ID // PK
Name
...
- - - - - - - - - -
Taggable
ID // PK
...
- - - - - - - - - -
TagAssignment
Tag_ID // FK -> Tag.ID
Taggable_ID // FK -> Taggable.ID
...
- - - - - - - - - -
EntityOne
Taggable_ID // FK -> Taggable.ID
...
- - - - - - - - - -
EntityTwo
Taggable_ID // FK -> Taggable.ID
...
次に、エンティティ クラスに独自の主キーを持たせるか、 andの事実上の主キーとしてEntityOne.TaggableID
andを使用しますか?EntityTwo.TaggableID
EntityOne
EntityTwo
ほとんどの場合、私は用心深く、エンティティに独自の ID を持たせます。
- - - - - - - - - -
EntityOne
ID // PK
Taggable_ID // FK -> Taggable.ID (Nullable)
...
- - - - - - - - - -
EntityTwo
ID // PK
Taggable_ID // FK -> Taggable.ID (Nullable)
...
これは、各エンティティが の対応するインスタンスを持つ必要がないため、Taggable
エンティティに関連するすべてのコードがタグを認識している必要もありません。ただし、タグ付けがシステム内で本当に遍在する場合、およびエンティティの他の「共通の祖先」(つまり、 以外Taggable
) が必要ないことが確実な場合は、「組み込み」なしで済む可能性があります。エンティティの ID。
NB : 私はこのようなものを実装しようとしたことはないので、私の推奨事項はすべて純粋に理論的なものです。明らかな欠陥が見られない場合は、私を撃たないでください。:-)
ビル・カーウィンのコメントに応えて:
おっしゃる通りです。上記の設計では、複数のエンティティが同じ を参照することは妨げられませんTaggable
。しかし:
私が言ったように、すべては要件に依存します。Taggable
エンティティの唯一の「共通の祖先」になることが確実な場合は、 Taggable_ID
FK をエンティティの PK として使用してもかまいません。しかし、たとえば、たまたま「タグ付け可能」なエンティティが「監視可能」(通知、通知スケジュールなどを考えてください)または「何でも可能」でなければならない場合はどうなりますか :-)? エンティティを結び付けにくいことで、これらすべての「能力」を遮断できますTaggable
か?
1つのタグ付け可能で1つのエンティティの制約をDBレベルで強制したい場合...私の知る限り、FKをPKとして機能させずにそれを行う一般的な方法が少なくとも1つあります。とにかく他の機能に役立つかもしれません)。
これらの線に沿った何かがあれば、ケーキを食べて食べることができます:
- - - - - - - - - -
Taggable
ID // PK
Type
...
- - - - - - - -
Constraint: (ID, Type) is unique
- - - - - - - - - -
EntityOne
ID
Taggable_ID
Taggable_Type // Constraint: always = 'EntityOne'
...
- - - - - - - -
FK: (Taggable_ID, Taggable_Type) -> (Taggable.ID, Taggable.Type)
もちろん、これはすべて、エンティティをタグ付け可能に結び付けるよりも複雑です。しかし、私の謙虚な意見では、元の質問によって提供された狭い全体像に加えて、何を考慮すべきかについて議論しようとしていました.