【问题标题】:How to read dynamic properties from database如何从数据库中读取动态属性
【发布时间】:2013-02-19 02:58:57
【问题描述】:

我会尽我所能解释我的场景。我的数据库中有以下表格:

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 的其他实体,例如CpuHddCameraPcCaseGraphicCard、@987654333 @、Gps

但我认为 这很愚蠢,因为我可以在域中使用 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);
                    }
                }

【问题讨论】:

  • 是否有任何理由需要在模型类中提供这些属性,而不是让 Product 有一个 Dictionary&lt;string, object&gt;(或类似的东西)?
  • 最简单的方法是使用DataTables。然后你只需要一个 sql-query 和一个 SqlDataAdapter 来填充表格。
  • @millimoose 一开始我想到了Dictionary。但我不知道这种情况是否有一些不同的解决方案。或者Dictionary实际上是唯一或最好的解决方案。
  • @1110 那么看来您要的是安全毯。您如何尝试使用Dictionary,这似乎是显而易见的选择,如果这导致您的设计出现问题,请回来询问上述问题?
  • @1110 你也可以看看 Steve Yegge 的帖子,他称之为the Properties pattern。免责声明:它很长,而且他有可能每个帖子不止一次出轨。

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


【解决方案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"});

【讨论】:

  • 我不能这样处理。 Properties 属性应该是动态的,所以我无法阅读它,因为我不知道属性的名称。
  • 它是“动态的”,您只需用返回的任何内容填充每个 ProductProperty
【解决方案2】:

你原来的方法

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    • 2020-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多