2011-08-26 1 views
5

La situazione è che ho una tabella che modella un'entità. Questa entità ha un numero di proprietà (ciascuna identificata da una colonna nella tabella). Il fatto è che in futuro avrei bisogno di aggiungere nuove proprietà o rimuovere alcune proprietà. Il problema è come modellare sia il database che il codice corrispondente (usando C#) in modo che quando appare una tale occasione sarebbe molto facile semplicemente "avere" una nuova proprietà.Generics e database - un problema di progettazione

All'inizio c'era solo una proprietà, quindi avevo una colonna. Ho definito la proprietà corrispondente nella classe, con il tipo e il nome appropriati, quindi ho creato stored procedure per leggerlo e aggiornarlo. Poi arrivò la seconda proprietà, rapidamente copia-incollava, cambiava nome e tipo e un po 'di SQL ed eccolo lì. Ovviamente questo non è un modello adatto per il futuro. A questo punto alcuni di voi potrebbero suggerire un ORM (EF o altro) perché questo genererà automaticamente SQL e codice ma per ora non è un'opzione per me.

Ho pensato di avere solo una procedura per leggere una proprietà (per nome della proprietà) e un'altra per aggiornarla (per nome e valore) poi alcune procedure generali per leggere un mazzo o tutte le proprietà per un'entità nella stessa istruzione . Questo può sembrare facile in C# se si considera l'uso di generici, ma il database non conosce i generici quindi non è possibile avere una soluzione tipizzata forte.

Mi piacerebbe avere una soluzione che sia "fortemente tipizzata possibile", quindi non ho bisogno di fare molti casting e analisi. Definirei le proprietà disponibili nel codice in modo da non indovinare cosa hai a disposizione e utilizzare stringhe magiche e simili. Quindi il processo di aggiunta di una nuova proprietà nel sistema significherebbe solo aggiungere una nuova colonna alla tabella e aggiungere una nuova "definizione" di proprietà nel codice (ad esempio in un enum).

+0

Perché non puoi usare l'EF? I geni di Microsoft hanno già capito e fatto un sacco di lavoro per voi in questo senso. Non oso vederti reinventare la ruota. – Jay

+0

Sì, non capisco perché è necessario evitare un ORM. (Inoltre, non ho idea di cosa abbia a che fare C# generics con questo) –

+0

Sono d'accordo, ma EF è un po 'più avanti per quanto riguarda l'architettura, quindi non posso ancora usarlo. – CyberDude

risposta

2

Sembra che si vuole fare questo:

MyObj x = new MyObj(); 
x.SomeProperty = 10; 

Hai una tabella creata per questo, ma non volete mantenere alterando quel tavolo quando si aggiunge

x.AnotherProperty = "Some String"; 

È necessario normalizzare i dati della tabella in questo modo:

-> BaseTable 
    RecordId, Col1, Col2, Col3 

-> BaseTableProperty 
    PropertyId, Name 

-> BaseTableValue 
    ValueId, RecordId, PropertyId, Value 

la classe sarà simile così:

public class MyObj 
{ 
     public int Id { get; set; } 
     public int SomeProperty { get; set; } 
     public string AnotherProperty { get; set; } 
} 

Quando si crea l'oggetto dal DL, si enumera il set di record. Quindi scrivi il codice una volta che controlla la proprietà come lo stesso nome della tua configurazione (BaseTableProperty.Name == MyObj.<PropertyName> - e poi prova il tipo cast come quel tipo enumerando il set di record

Quindi, aggiungi semplicemente un'altra proprietà a l'oggetto, un altro record al database in BaseTableProperty, e quindi è possibile memorizzare i valori per quel ragazzo in BaseTableValue

Esempio:.

RecordId 
======== 
1 

PropertyId   Name 
==========   ==== 
1     SomeProperty 

ValueId  RecordId  PropertyId  Value 
=======  ========  ==========  ===== 
1   1    1    100 

si dispone di due set di risultati, una per i dati di base, e uno uniti dalle tabelle Proprietà e Valore.Come si enumera ogni record, si vede un nome di SomeProperty - esiste typeof(MyObj).GetProperty("SomeProperty")? Sì? Di che tipo è il tipo di dati? int? Ok, quindi provare a convertire il "100" per int impostando la proprietà:

propertyInfo.SetValue(myNewObjInstance, Convert.ChangeType(dbValue, propertyInfo.PropertyType), null); 

Per ogni proprietà.

+0

Avvicinarsi ma non voglio o non devo dichiarare ogni proprietà nella classe. Succede raramente che ho bisogno di più di una proprietà alla volta. La maggior parte delle volte ho l'ID oggetto e ho bisogno di sapere solo una delle proprietà. Ecco perché stavo andando ad avere un metodo generale 'GetProperty (int objectID, string propertyName)'. – CyberDude

+0

Lo accetterò poiché è il più vicino alla soluzione che prenderò. – CyberDude

0

Anche se hai detto che non puoi usarli, è quello che fa la maggior parte degli ORM. A seconda di quale si utilizza (o anche di creare se si tratta di un'esperienza di apprendimento), essi variano notevolmente in termini di complessità e prestazioni. Se si preferisce un ORM leggero, controllare Dapper.Net. Fa uso anche di generici, così puoi controllare il codice, vedere come funziona e creare la tua soluzione, se necessario.