2010-12-30 14 views
5

tengo una estructura jerárquica de clase así:Llenar una estructura jerárquica con la clase de datos

Categoría -> Plantilla -> Instancia

Una categoría contiene varias plantillas, una plantilla contiene varias instancias.

Si consultar los datos de la base de datos a través de una unión sobre los 3 tablas, los datos se ve algo como esto:

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" 

(sólo un ejemplo, las tablas de datos reales tienen mucho más columnas)

¿Cuál es la mejor/manera común en C# para completar las clases con este tipo de datos cuando lo recorre con un lector de datos?

Desde la parte superior de mi cabeza me gustaría hacerlo de esta manera:

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"]); 
} 

¿Existe una solución mejor, más elegante para llenar los objetos de clases jerárquicas? Tal vez usando LINQ o Diccionarios?

Nota: Esta pregunta está relacionada con mi otra pregunta acerca del best way to gather hierarchical data from a DB. Lo dividí porque estos son dos temas separados.

Respuesta

3

Lo que hace parece ser una buena manera de hacerlo. Solo asegúrate de ordenar los datos en tu consulta por las columnas de ID que tienes. Ordenar por categoría y plantilla. Esto asegurará que no regrese a uno de esos ID y cree el objeto nuevamente.

Además, si una plantilla puede pertenecer a múltiples categorías, deberá almacenar cada plantilla en una lista en alguna parte para asegurarse de no duplicarlas sobre las categorías.

+0

Gracias para señalar eso, una plantilla puede estar en múltiples categorías. A pesar de que todavía estoy descontento con la obtención de datos que son iguales para muchas filas de la primera, creo que lo implementaré de esta manera, si no hay una mejor sugerencia. – magnattic

-1

algo como lo siguiente se le proporcionará un enfoque directo a la clase:

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

Sin ofender, pero ¿leyó la pregunta? Consulto los datos de una base de datos y su respuesta ni siquiera tiene nada que ver con la estructura de datos jerárquica. – magnattic

+0

Sí, lo leí y es por eso que le di una solución que toma su estructura y la coloca en un objeto. Puse nuevo en lugar de su objeto Categorías. Supuse que sabías que también podrías crear una instancia de tu plantilla y objetos de instancia en línea, lo que te daría la jerarquía que deseas. – phillip

+0

Ahora actualicé la publicación para que pueda verla dentro de una jerarquía.Por lo general, cuando escribo este tipo de código no lo pongo todo en línea de esta manera: generalmente los creo de forma individual y luego reúno los objetos secundarios en sus padres, pero eso es solo una preferencia. – phillip

1

Al leer desde el lector de datos, rellenar un objeto con los datos de cada fila. En este punto no se preocupe por los duplicados:

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])); 
} 

donde

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; 
    } 
} 

continuación, puede utilizar LINQ para obtener los niveles individuales de la jerarquía a cabo:

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

Cuestiones relacionadas