Заполнение иерархической структуры классов данными - PullRequest
5 голосов
/ 30 декабря 2010

У меня есть иерархическая структура классов, например:

Категория -> Шаблон -> Экземпляр

Категория содержит несколько шаблонов, шаблон содержит несколько экземпляров.

ЕслиЯ запрашиваю данные из базы данных через объединение всех трех таблиц, данные выглядят примерно так:

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"

(просто пример, таблицы реальных данных имеют гораздо больше столбцов)

Каков наилучший / распространенный способ в C # заполнять классы данными такого типа при циклическом переборе их с помощью устройства чтения данных?

Сверху головы я бы сделал это следующим образом:

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

Есть ли лучшее, более элегантное решение для заполнения объектов иерархического класса?Может быть, используете LINQ или словари?

Примечание. Этот вопрос связан с моим другим вопросом о лучшем способе сбора иерархических данных из БД .Я разделил это, потому что это две отдельные проблемы.

Ответы [ 3 ]

3 голосов
/ 30 декабря 2010

То, что вы делаете, кажется хорошим способом работы с этим. Просто убедитесь, что вы сортируете данные в вашем запросе и столбцы идентификаторов, которые у вас есть. Сортировать по категории, а затем по шаблону. Это гарантирует, что вы не вернетесь к одному из этих идентификаторов и не создадите объект снова.

Также - если шаблон может быть в нескольких категориях, вам придется хранить каждый шаблон в списке где-нибудь, чтобы не дублировать их по категориям.

1 голос
/ 31 декабря 2010

Когда вы читаете из устройства чтения данных, заполняйте объект данными из каждой строки.На данный момент не беспокойтесь о дубликатах:

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

, где

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

, тогда вы можете использовать LINQ, чтобы получить отдельные уровни иерархии:

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

0 голосов
/ 30 декабря 2010

Нечто подобное даст вам прямой подход к классу:

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