2010-04-24 12 views
5

Devo aggiungere funzionalità a un'applicazione esistente e ho riscontrato una situazione di dati che non so come modellare. Mi sto limitando alla creazione di nuove tabelle e codici. Se devo modificare la struttura esistente, penso che il mio cliente possa rifiutare la proposta ... anche se è l'unico modo per farlo correttamente è quello che dovrò fare.Come modellare una relazione mutuamente esclusiva in SQL Server

Ho una tabella di articoli che può essere collegata a un numero qualsiasi di tabelle e queste tabelle potrebbero aumentare nel tempo. L'articolo può essere collegato solo a un altro tavolo, ma il record nell'altra tabella potrebbe avere molti elementi collegati ad esso.

Esempi di tabelle/entità collegate a sono Person, Vehicle, Building, Office. Queste sono tutte tabelle separate.

Esempio di articoli sono Pen, Stapler, Cushion, Tyre, A4 Paper, Plastic Bag, Poster, Decoration"

Per esempio un Poster possono essere assegnati ad un Person o Office o Building. In futuro, se aggiungono una tabella Conference Room, potrebbe essere aggiunta anche a quella.

I miei pensieri sono intital:

Item 
{ 
    ID, 
    Name 
} 

LinkedItem 
{ 
    ItemID, 
    LinkedToTableName, 
    LinkedToID 
} 

Il campo LinkedToTableName poi mi permetterà di identificare la tabella corretta per collegare nel mio codice.

Non sono eccessivamente soddisfatto di questa soluzione, ma non riesco a pensare a nient'altro. Per favore aiuto! :)

Grazie!

+0

Sarebbe utile se si explaned un po 'di più su che tipo di dati che si stanno memorizzando, e perché; ad esempio, gli articoli post del blog, persone o articoli in un supermercato, ecc.? Cosa rappresentano le tabelle di destinazione? Penso che la tua astrazione sia rotta, ma è quasi impossibile dire perché, o suggerire un approccio diverso senza conoscere il problema che stai cercando di risolvere con esso. –

+0

Grazie Rowland. Ho provato ad aggiungere alla mia domanda. Vedi Modificato D. Verrà modificato nuovamente se le informazioni non sono ancora sufficienti :) – littlechris

risposta

12

Non è una buona pratica memorizzare i nomi di tabelle come valori di colonna. Questo è un brutto attacco.

Esistono due modi standard per eseguire ciò che si sta tentando di fare. Il primo si chiama ereditarietà a tavolo singolo. Ciò è facilmente comprensibile dagli strumenti ORM, ma scambia alcune normalizzazioni. L'idea è che tutte queste entità - Person, Vehicle, qualunque sia - sono memorizzate nella stessa tabella, spesso con diverse colonne non utilizzate per ogni voce, insieme a un campo discriminatore che identifica il tipo di entità.

Il campo discriminatore è in genere un tipo intero, che è mappato su qualche enumerazione nel codice. Potrebbe anche essere una chiave esterna di una tabella di ricerca nel database, che identifica quali numeri corrispondono a quali tipi (non sono nomi di tabelle, solo descrizioni).

L'altro modo per fare ciò è ereditarietà di più tabelle, che è migliore per il database ma non facile da mappare nel codice. A tale scopo, disponendo di una tabella di base che definisce alcune proprietà comuni di tutti gli oggetti, ad esempio un ID e un nome, e tutte le tabelle "specifiche" (Person ecc.) Utilizzare l'ID di base come chiave esterna univoca (di solito anche la chiave primaria).

Nel primo caso, l'esclusività è implicita, poiché tutte le entità si trovano in una tabella. Nel secondo caso, la relazione è compresa tra Item e base ID, che garantisce anche l'univocità.

Si noti che con l'ereditarietà di più tabelle, si presenta un problema diverso: non è possibile garantire che un ID di base sia utilizzato esattamente da una tabella di ereditarietà. Potrebbe essere usato da molti, o non usato affatto. Questo è il motivo per cui gli schemi di ereditarietà di tabelle multiple di solito hanno anche una colonna discriminante, per identificare quale tabella è "attesa". Ancora una volta, questo discriminatore non ha un nome di tabella, contiene un valore di ricerca che il consumatore può (o non può) usare per determinare a quale altra tabella si unirà.

L'ereditarietà di più tabelle è più simile allo schema corrente, quindi consiglierei di andare con quello a meno che non sia necessario utilizzarlo con Linq su SQL o un ORM simile.

Vedere qui per un buon tutorial dettagliato: Implementing Table Inheritance in SQL Server.

0

la tabella dei collegamenti è ok.

il problema che si avrà è che è necessario generare SQL dinamico in fase di esecuzione. sql con parametri non consente in genere agli oggetti dell'elenco FROM di essere parametri.

Se vuoi evitare questo, potresti essere in grado di denormalizzare un po ', ad esempio creando una tabella per contenere l'id (supponendo che gli ID siano unici tra le altre tabelle) e il tipo id che rappresenta la tabella è l'origine, e una descrizione generata - es il valore del nome dal record iniziale.

si attiverà la creazione di questo elenco denormalizzato quando le informazioni di base vengono modificate, e si potrebbe usare questo per le query generalizzate, e quindi ricorrere alle query dinamiche quando necessario in fase di runtime.

9

Trova qualcosa di comune a persona, veicolo, costruzione, Ufficio. Per la mancanza di un termine migliore ho usato Entity. Quindi implementare la relazione super-tipo/sottotipo tra l'entità ei relativi sottotipi. Si noti che EntityID è un PK e un FK in tutte le tabelle di sottotipo. Ora è possibile collegare la tabella Articolo all'entità Entità (proprietario). In questo modello, un può appartenere a una sola Entità; uno L'entità può avere (proprio) molti articoli .

model_mutually_exclusive_01

+1

Quale software hai utilizzato per generare quell'immagine? – goat

+0

@chris, Visio 2007 –

Problemi correlati