Vedo tre diverse soluzioni dal punto di vista del design del DB. Non sono sicuro di come il tuo layer ORM (entity framework) apparirà basato su questi progetti, ma mi piace avvicinarmi a queste cose da un progetto di DB.
Opzione 1
Quella che hai menzionato, ma per applicare l'integrità referenziale devi aggiungere un'altra colonna:
CREATE TABLE 'likes' (
'target' int(11),
'targetTypeID' int(11),
'user_id' int(11),
'created_at' timestamp
)
Quindi avresti bisogno di una tabella targetType, che contiene 3 voci; Video, immagine e commento. Sulla base di questa tabella, è possibile scrivere un trigger per applicare l'integrità referenziale: si controllerà il valore targetTypeID e quindi si verificherà il valore target corrispondente. . Un po 'incasinato, ma funzionerebbe. Se vuoi semplificare la procedura, puoi aggiungere TargetTypeID come colonna alla tabella Video, Immagine e Commento, quindi puoi eseguire una query in questo modo:
Select l.*
from Likes l
left outer join image i on l.target = i.imageid and l.targettypeid = i.targettypeid
left outer join video v on l.target = v.videoid and l.targettypeid = i.targettypeid
left outer join comment c on l.target = c.commentid and l.targettypeid = i.targettypeid
che ti aiuterà ad evitare di entrare accidentalmente in una fila di "Video Mi piace" nella tabella Mi piace alla tabella sbagliata, ad esempio come una riga "Immagine". E sì, se è possibile, succederà sicuramente .
Opzione due
Crea la tua tabella in questo modo:
CREATE TABLE 'likes' (
LikeID int primary key,
ImageID int null,
VideoID int null,
CommentID int null,
'user_id' int(11),
'created_at' timestamp
)
È quindi possibile inserire un vincolo (o un trigger) che indica che "IDImmagine" o "IDVideo" o "IDDIP" devono essere compilati. Il vantaggio principale di questo design è che è possibile applicare integralmente l'integrità referenziale utilizzando il DB. Il lato negativo è che stai "sprecando" due colonne che saranno sempre nulle. L'altro lato negativo è che le tue query saranno simili a questa:
Select l.*
from Likes l
left outer join image i on l.imageid = i.imageid
left outer join video v on l.videoid = v.videoid
left outer join comment c on l.commentid = c.commentid
che è alquanto fastidioso. Ma forse non avrai bisogno di fare quel genere di cose molto spesso, specialmente se metti le cose comuni (es. Nome, descrizione) nella tabella dei Mi piace.
Opzione tre
Uso di "ereditarietà" o una tabella di base. Crea una nuova tabella chiamata "ItemLike":
create table ItemLike (
ItemLikeID int,
TargetTypeID int,
ImageID int null,
VideoID int null,
CommentID int null,
)
e cambia la tua tabella simile in questo modo:
CREATE TABLE 'likes' (
LikeID int primary key,
ItemLikeID int foreign key,
'user_id' int(11),
'created_at' timestamp
)
molto simile alla seconda risposta ma semplicemente aggiungendo un altro livello di astrazione e potrebbe rendere più belle le classi del tuo Entity Framework. Un po 'inutile dal punto di vista del progetto DB, a meno che tu non voglia rendere ItemLikeID nullable (non riesco a capire il motivo per cui lo faresti), ma potrebbe rendere più facile il partizionamento della tabella se ottieni tanti e tanti dati nella tua tabella simile. I tuoi join quindi assomigliano a questo:
Select l.*
from Likes l
inner join ItemLike il on l.ItemLikeID = il.ItemLikeID
left outer join image i on il.imageid = i.imageid
left outer join video v on il.videoid = v.videoid
left outer join comment c on il.commentid = c.commentid
Oppure potresti usare un database NoSQL e tutti i tuoi problemi andranno via! < / sarcasmo >