2010-12-30 20 views
5

ho una struttura di classe gerarchica come questa:Riempire una struttura di classe gerarchica con i dati

Categoria -> Modello -> Istanza

Una categoria contiene più modelli, un modello contiene più istanze.

Se interrogo i dati dal database tramite un join su tutte e 3 le tabelle, i dati sembra qualcosa di simile:

CategoryID | CategoryName | CategoryType | TemplateID | TemplateName | TemplateXYZ | InstanceID | InstanceName 
1 | "CatA" | "TypeX" | 1 | "TempA" | "X" | 1 | "InstA" 
1 | "CatA" | "TypeX" | 1 | "TempA" | "X" | 2 | "InstB" 
1 | "CatA" | "TypeX" | 1 | "TempA" | "X" | 3 | "InstC" 
1 | "CatA" | "TypeX" | 1 | "TempB" | "Y" | 4 | "InstD" 

(solo un esempio, le tabelle di dati reali hanno molto più colonne)

Qual è il modo migliore/comune in C# per riempire le classi con questo tipo di dati quando si passa attraverso di esso con un lettore di dati?

Dalla cima della mia testa vorrei fare in questo modo:

while(data.Read()) 
{ 
    // Create new objects each time the ID changes and read the data from the first row 
    if(data["CategoryID"] != lastCategoryID) { 
    lastCategoryID = data["CategoryID"]; 
    cat = new Category(data["CategoryName"], data["CategoryType"]); 
    catList.Add(cat); 
    } 
    if(data["TemplateID"] != lastTemplateID) { 
    lastTempateID = data["TemplateID"]; 
    template = new Template(data["TemplateName"], data["TemplateXYZ"])); 
    cat.Templates.Add(template); 
    } 
    template.Instances.Add(new Instance(data["InstanceID"], data["InstanceName"]); 
} 

Esiste una soluzione migliore e più elegante per riempire gli oggetti di classe gerarchica? Forse usando LINQ o dizionari?

Nota: questa domanda è correlata alla mia altra domanda relativa allo best way to gather hierarchical data from a DB. L'ho diviso perché si tratta di due problemi separati.

risposta

3

Quello che fai sembra un buon modo per lavorarci. Assicurati di ordinare i dati nella tua query per e le colonne ID che hai. Ordina per categoria, quindi modello. Questo assicurerà di non tornare a uno di quegli ID e di creare nuovamente l'oggetto.

Inoltre, se un modello può essere in più categorie, è necessario memorizzare ciascun modello in un elenco da qualche parte per assicurarsi di non duplicarlo su categorie.

+0

Grazie per indicarlo, un modello può effettivamente essere in più categorie. Anche se sono ancora in qualche modo scontento di ottenere dati che siano uguali per molte righe solo dal primo, suppongo che lo implementerò in questo modo, se non c'è un suggerimento migliore. – magnattic

-1

qualcosa come il seguente dovrebbe fornire un approccio diretto alla classe:

string[] allLines = File.ReadAllLines("datafile.dat"); 

var query = from line in allLines 
      let data = line.Split('|') 
      select Category 
       { 
        CategoryID = data[0], 
        CategoryName = data[1], 
        CategoryType = data[2], 
        Template = new Template { TemplateID = data[3], 
               TemplateXYZ = data[4], 
               Instance = new Instance { InstanceID = data[5], 
        InstanceName = data[6] } 
            } 
       }; 
+3

Senza offesa, ma hai letto anche la domanda? Invito i dati da un database e la tua risposta non ha nemmeno nulla a che fare con la struttura gerarchica dei dati. – magnattic

+0

Sì, l'ho letto ed è per questo che ti ho dato una soluzione che prende la tua struttura e la mette in un oggetto. Metto di nuovo in opposizione al tuo oggetto Categorie. Supponevo che tu sapessi che in quel momento potevi istanziare anche il tuo modello e gli oggetti di istanza in linea che ti avrebbero dato la gerarchia che volevi. – phillip

+0

Ora ho aggiornato il post in modo da poterlo vedere all'interno di una gerarchia.Di solito quando scrivo questo tipo di codice non lo metto tutto in linea come questo - di solito li creo individualmente e poi uniamo gli oggetti figlio ai loro genitori, ma questa è solo una preferenza. – phillip

1

Come si legge dal lettore di dati, compilare un oggetto con i dati provenienti da ogni riga. A questo punto non ti preoccupare i duplicati:

var rawData = new List<Incoming>(); 
while (data.Read()) 
{ 
    rawData.Add(new Incoming(data[0], data[1],data[2],data[3],data[4],data[5],data[6],data[7])); 
} 

dove

public class Incoming 
{ 
    public int CategoryID { get; set; } 
    public string CategoryName { get; set; } 
    public int CategoryType { get; set; } 
    public int TemplateID { get; set; } 
    public string TemplateName { get; set; } 
    public int TemplateXYZ { get; set; } 
    public int InstanceID { get; set; } 
    public string InstanceName { get; set; } 

    public Incoming(int categoryID , string categoryName , int categoryType , int templateId,string templateName ,int templateXYZ , int instanceID , string instanceName ) 
    { 
     CategoryID =categoryID; 
     CategoryName = categoryName; CategoryType = categoryType; TemplateID = templateId; 
     TemplateName = templateName; TemplateXYZ = templateXYZ; InstanceID = instanceID; InstanceName = instanceName; 
    } 
} 

quindi è possibile utilizzare LINQ per ottenere i singoli livelli della gerarchia out:

var categories = rawData.GroupBy (d => d.CategoryID );

Problemi correlati