如何从数据库中读取动态属性

时间:2013-03-04 21:25:35

标签: c# ado.net data-access-layer sqldatareader

我会尽力以最好的方式解释我的情景。我的数据库中有以下表格:

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

因此,目标是拥有属于某个类别的产品列表,并且每个类别可以在“PropertyValues”表中包含具有值的“n”个属性。我有一个基于'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的其他实体,例如CpuHddCameraPcCaseGraphicCardMobilePhoneGps等。
但我认为这是愚蠢的,因为我可以结束这与域中 200+个实体相关。

在这种情况下你会做什么? 如何阅读以及放置此动态属性的位置?

更新 - 某种解决方案

好的,基于 @millimoose 建议Dictionary @Tim Schmelter 想法使用DataTable对象,我找到了一些解决方案。
现在......这是有效的,我得到数据读取它们,我可以显示它们 但我仍然需要聪明的人提供比我更好的建议我做得好或者我应该更好地处理这个或者我做了一些 spageti代码。 所以我在这里做了什么:

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

2 个答案:

答案 0 :(得分: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"});

答案 1 :(得分:0)

您原来的方法

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

非常好。我会使用自定义集合,更好的命名,因此意图更清晰。

您还可以使用C#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;
    }
}

有些相关问题:How to convert a data reader to dynamic query results