Как читать динамические свойства из базы данных

Я попытаюсь объяснить свой сценарий наилучшим образом. В моей базе данных есть следующие таблицы:

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

Таким образом, цель состоит в том, чтобы иметь список продуктов, принадлежащих какой-либо категории, и каждая категория может иметь "n" количество свойств со значениями в таблице "PropertyValues". У меня есть запрос, который возвращает данные на основе "categoryId", поэтому я всегда могу получить разные результаты из базы данных:

Для категории CPU:

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

Для категории HDD:

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

Поэтому, основываясь на категориях из моего запроса, я всегда могу получить разные номера столбцов и имена. Для доступа к базе данных я использую простой вызов ADO.NET для хранимой процедуры, возвращающей результат. Но поскольку результат запроса динамичен в природе, я не знаю, что это хороший способ прочитать эти данные.

Я создал объект Product, но Я запутался, как это сделать: ( Я думал, что могу создать объект Product и сделать другие объекты, которые наследуют Product, как Cpu, Hdd, Camera, PcCase, GraphicCard, MobilePhone, Gps и т.д.

но я думаю, что , что это глупо, потому что я могу закончить это с 200 + сущностями в домене.

Что бы вы сделали в этой ситуации?
Как читать и где размещать эти динамические свойства ?

UPDATE - некоторое решение

Все в порядке на основе предложения @millimoose для Dictionary и идеи @Tim Schmelter для использования объекта DataTable. Я пришел к определенному решению.
Теперь... это работает, я получаю данные, читаю их, и я могу их отобразить.
Но мне все еще нужен совет от более умных людей, чем я, на , я сделал это хорошо, или я должен справиться с этим лучше, или я сделал несколько spageti code. Итак, вот что я сделал:

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

У вас есть продукт, куча категорий, и каждая категория имеет кучу свойств.

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

вы можете сохранить свойства продукта в списке/словаре

то вы просто добавляете свойства к продукту

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

или если его имя/значение

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

Ответ 2

Ваш оригинальный подход

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

неплохо. Я бы использовал пользовательскую коллекцию, но с лучшим названием, так что цель понятна.


Вы также можете использовать функцию С# 4.0 dynamic, которая более крутая, но я не уверен, какую пользу она дает в вашем случае. Вы могли бы сделать что-то вроде

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

Совсем связанный вопрос: Как преобразовать считыватель данных в динамические результаты запроса