(In ritardo alla festa, ma non ho potuto resistere)
Risolviamo alcuni malintesi.
Joins are expensive
Rispetto a cosa? Ovviamente, leggere un tavolo piatto è "più economico" di unire tabelle, ma qualsiasi RDBMS maturo è altamente ottimizzato per l'esecuzione di join perché sono inevitabilmente parte di progetti di database validi. I vincoli sui vincoli di chiave esterna (i più comuni) sono particolarmente ottimizzati. E, naturalmente, l'indicizzazione corretta è indispensabile.
we should keep our database normalized and with the least queries executed as possible
Il modo in cui lo poni, sembra essere una conseguenza di impedire questi "costosi" join. Il contrario è vero. La normalizzazione genererà sempre più tabelle e, quindi, più join per interrogare gli stessi dati di uno schema di dati denormalizzato. (Beh, per essere onesti con te, in seguito dici "Preveniamo EAV e quindi, Joins.").
We should avoid an Entity-Attribute-Value approach (EAV), unless denormalization becomes desirable
L'EAV è quasi una denormalizzazione. Ho l'impressione che tu non comprenda appieno cos'è l'EAV.
In un progetto EAV, attributi di una relazione (ovvero campi o colonne , di una tabella del database ) sono presi da una relazione e memorizzati come record in una tabella Attributi. I valori sono memorizzati in un'altra tabella con chiavi esterne alla tabella Attributi e una tabella Entità . Un record nelle tabelle Attributi esprime un fatto: questo è il valore X dell'attributo Y nell'entità Z.
Quindi con EAV, se applicato con rigore, se vuoi conoscere la data di inizio, la data di fine e il costo di un torneo, dovrai eseguire una query sulla tabella PGTournament e unirti a Attributo e Valore (con WHERE
condizione per gli attributi). Si tratta di due join anziché zero senza EAV!
Quasi sempre, l'EAV è un cattivo design. Va usato quando non ci sono alternative (ad esempio nelle applicazioni di laboratorio in cui nuove analisi per campioni possono essere inventate ogni giorno - un set fisso di campi in una tabella di esempio non è sufficiente).
Nel tuo caso, non vedo alcun motivo per introdurre l'EAV: non capisco nemmeno perché lo fai crescere. Penso che sia perché confondi EAV con le associazioni 1: 1. Continua a leggere.
Which means that we should adhere to OOP's SOLID Principles
Il modello di classe EF fa parte di un livello di accesso ai dati . Non è un modello di dominio! Almeno, non è la sua prima responsabilità ad esserlo. Le proprietà della classe dovrebbero facilitare l'accesso ai dati. Ciò significa che ci saranno relazioni bidirezionali e proprietà di identificazione, per menzionare due anti-pattern OOP. E il vero bummer OOP: le classi tendono ad essere altamente anemiche. Ogni volta che le classi EF possono essere utilizzate come classi di dominio, questo è un semplice bonus .
virtual properties without the List<>
type
Tali proprietà sono note come proprietà di navigazione perché "navigano" verso altre entità. Gli elenchi sono proprietà di navigazione della raccolta e le proprietà del tipo di entità (senza il tipo List<>
) sono proprietà di navigazione di riferimento . Non devono essere virtuali. Quando sono virtuali, EF potrebbe essere in grado di caricare pigramente le proprietà.
this means that it is a one-to-one relationship
Perché? Le proprietà di navigazione di riferimento sono spesso la parte "1" di un'associazione 1: n. Penso che la maggior parte delle tue proprietà di riferimento siano così. Ad esempio, GameGenre
. Penso che ci siano molti tornei con lo stesso GameGenre
. È un'associazione 1
(genere) a n
(torneo), anche se GameGenre
non ha una raccolta Tournaments
. Forse solo TournamentSettings
e MainImage
sono associazioni 1: 1 effettive.
Le associazioni 1: 1 distribuiscono i dati appartenenti a un'entità su più tabelle. Ci possono essere ottime ragioni per farlo. Uno di questi è facilitare l'interrogazione di dati leggeri senza il pesante carico utile di qualche blob, come MainImage
. Un altro separa i dati sensibili dai dati pubblici. O dati comuni (spesso interrogati) da dati specializzati (a volte interrogati), forse il tuo TournamentSettings
.
Ora, finalmente, la tua domanda:
should I favor a fully normalized design over a OOP Approach when modeling in Entity Framework?
Stai confrontando mele e arance. La progettazione normalizzata è database, OOP è un modello di classe. Ma se c'è qualcosa da favorire, è il design normalizzato. Una progettazione di database ben strutturata è fondamentale per qualsiasi applicazione basata su dati. Tutto il resto segue. Il modello di classe EF necessariamente rifletterà strettamente la struttura del database. Come ho detto sopra: deve essere visto come un livello di accesso ai dati.
Ma ogni volta che modellate la logica di business, ovviamente, provate a farlo nel modo più SOLIDO possibile. Ciò significa che a volte dovrai compilare un modello di dominio specializzato dalle entità interrogate da EF e, a volte, le classi EF possono essere estese per incapsulare comportamenti e dati (che è tutto ciò che riguarda OOP).