2013-03-04 10 views
6

Postaram się wyjaśnić mój scenariusz najlepiej jak potrafię. Mam następujące tabele w mojej bazy danych:Jak odczytać właściwości dynamiczne z bazy danych

Products{ProductId, CategoryId ...} 
Categories{CategoryId ...} 
CategoryProperties{CategoryPropertyId, CategoryId, Name ...} 
PropertyValues{ProductId, CategoryPropertyId, Value ...} 

Więc celem jest wykaz produktów mają należący do jakiejś kategorii, a każda kategoria może mieć „n” szereg właściwości z wartościami w tabeli "PropertyValues. Mam kwerendy, która zwraca dane w oparciu o „IDkategorii”, więc zawsze mogę uzyskać różne wyniki z bazy danych:

Dla kategorii CPU:

intel i7 | CPU | Model | Socket | L1 Cash | L2 Cahs | etc. 

Dla kategorii HDD:

samsung F3 | HDD | Model | Speed | GB | etc. 

Tak więc w oparciu o kategorie z mojego zapytania zawsze mogę uzyskać różne numery kolumn i nazwy. Do dostępu do bazy danych używam prostego wywołania ADO.NET do procedury przechowywanej, która zwraca wynik. Ale ponieważ wynik zapytania jest dynamiczny w swojej naturze, nie wiem, jaki jest dobry sposób na odczytanie tych danych.

Zrobiłem podmiot Product ale jestem zdezorientowany jak zrobić to naprawdę :( myślałem, że mogę dokonać podmiot Product i wprowadzić inne podmioty, które dziedzicząProduct jak Cpu, Hdd, Camera, PcCase, GraphicCard, MobilePhone, Gps itp

ale myślę że to głupie ponieważ mogę zakończyć ten z 200+ jednostek w domenie.

Co zrobiłbyś w tej sytuacji?
Jak czytać i gdzie umieścić ten właściwości dynamiczne?

UPDATE - niektóre rozwiązania

porządku na podstawie @millimoose sugestię dla Dictionary i @Tim Schmelter pomysł, aby użyć DataTable obiekt doszedłem do jakiegoś rozwiązania.
Teraz ... to działa, otrzymuję dane do odczytu i mogę je wyświetlić.
Ale wciąż potrzebuję porady od mądrzejszych ludzi niż ja na czy zrobiłem to dobrze czy powinienem obsłużyć to lepiej albo zrobiłem jakiś kod spageti. Więc co zrobiłem:

public class Product 
    { 
     public Product() 
     { 
      this.DynamicProperties = new List<Dictionary<string, string>>(); 
     } 

     public List<Dictionary<string, string>> DynamicProperties { get; set; } 

    } 
... 
List<Product> products = new List<Product>(); 
... 
using (SqlDataAdapter a = new SqlDataAdapter(cmd)) 
       { 
        DataTable t = new DataTable(); 
        a.Fill(t); 

        Product p = null; 

        foreach (DataRow row in t.Rows) 
        { 
         p = new Product(); 
         foreach (DataColumn col in t.Columns) 
         { 
          string property = col.ColumnName.ToString(); 
          string propertyValue = row[col.ColumnName].ToString(); 

          Dictionary<string, string> dictionary = new Dictionary<string, string>(); 

          dictionary.Add(property, propertyValue); 

          p.DynamicProperties.Add(dictionary); 
         } 

         products.Add(p); 
        } 
       } 
+1

Czy istnieje jakikolwiek powód, trzeba mieć te właściwości dostępne w klasach modelowych, zamiast tylko o 'Product' mieć pojedynczy' Słownik '(lub coś w tym stylu)? – millimoose

+0

Najprostszym sposobem jest użycie 'DataTables'. Następnie potrzebujesz kwerendy sql i 'SqlDataAdapter', aby wypełnić tabelę. –

+0

@millimoose Najpierw myślałem o 'Słowniku'. Ale chciałbym wiedzieć, czy istnieje jakieś inne rozwiązanie tego scenariusza. Lub 'Słownik' jest tak naprawdę jedynym lub najlepszym rozwiązaniem. – 1110

Odpowiedz

1

Masz produkt, kilka kategorii, a każda kategoria ma kilka właściwości.

class Product 
{ 
    public int Id { get; set; } 
    public Category Category { get; set; } 
    public List<ProductProperty> Properties { get; set; } 
} 

class Category 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

class ProductProperty 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Value { get; set; } 
} 

można przechowywać właściwości produktu w postaci listy/słownika

następnie po prostu dodać właściwości do produktu

Properties.Add(new ProductionProperty() { Name="intel i7"}); 

lub jeśli jego nazwa/wartość

Properties.Add(new ProductionProperty() { Name="Speed", Value="150MB/s"}); 
+0

Nie mogę sobie z tym poradzić. Własność 'Właściwości' powinna być dynamiczna, więc nie mogę jej odczytać, ponieważ nie znam nazwy właściwości. – 1110

+0

jest "dynamiczny", wystarczy wypełnić każdą ProductProperty z czymkolwiek co wróci –

+0

zgodnie z aktualizacją –

0

Twoje oryginalne podejście

jest całkiem niezła. Chciałbym jednak użyć kolekcji niestandardowej, z lepszym nazewnictwem, aby intencje były wyraźniejsze.


Można również wykorzystać C# 4.0 w dynamic cechę, która więcej chłodne, ale nie jestem pewien, co daje korzyść to w Twoim przypadku. Można zrobić coś takiego,

public class Product 
{ 
    public List<dynamic> DynamicProperties { get; set; } 
} 

... 

conn.Open(); 
using (var reader = cmd.ExecuteReader()) 
{ 
    var p = new Products(); 
    p.DynamicProperties = reader.AsDyamic().ToList(); 

    //or 

    foreach (var item in reader.AsDynamic()) 
     yield return item; 
} 

// carry this extension method around 
public static IEnumerable<dynamic> AsDynamic(this IDataReader reader) 
{ 
    var names = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList(); 
    foreach (IDataRecord record in reader as IEnumerable) 
    { 
     var expando = new ExpandoObject() as IDictionary<string, object>; 
     foreach (var name in names) 
      expando[name] = record[name]; 

     yield return expando; 
    } 
} 

Nieco powiązane pytanie: How to convert a data reader to dynamic query results

Powiązane problemy