LINQ:将DataTable转换为包含数组的用户定义类

时间:2014-03-21 15:16:46

标签: c# .net linq .net-3.5

我有这个对象结构

public class Product
{
public int Id {get;set;}
public string DisplayName{get;set;}
public Ingredient[] Ingredents{get;set;}
}

public class Ingredient
{
 public int id{get;set;}
 public string Name{get;set;}
}

我有以下结果集的数据表

    Id | DisplayName  |  IngredientId | IngName
-------------+-------------------------+------------------------
    1  | Prod1         |   1           |  Ing1
    1  | Prod1         |   2           |  Ing2
    1  | Prod1         |   3           |  Ing3
    2  | Prod2         |   1           |  Ing1
    2  | Prod2         |   2           |  Ing2
    3  | Prod3         |   1           |  Ing1
    3  | Prod3         |   2           |  Ing2

我需要LINQ查询,它会给我产品列表如下: //描述结构的伪代码:

resultProductList =
{
  new Product() { Id = 1
                , DisplayName = "Prod1"
                , Ingredients = {
                                 new Ingredient{ Id = 1, Name = "Ing1" } 
                                , new Ingredient{ Id = 2, Name = "Ing2" } 
                                , new Ingredient{ Id = 3, Name = "Ing3" } 
                                }
 , new Product() { Id = 2
                , DisplayName = "Prod2"
                , Ingredients = {
                                 new Ingredient{ Id = 1, Name = "Ing1" } 
                                , new Ingredient{ Id = 2, Name = "Ing2" } 
                                }
 , new Product() { Id = 3
                , DisplayName = "Prod3"
                , Ingredients = {
                                 new Ingredient{ Id = 1, Name = "Ing1" } 
                                , new Ingredient{ Id = 2, Name = "Ing2" } 
                                }

}

我提到this,但我无法得到解决方案。

List<Product> lstContracttype = dsGetProducts.Tables[0]
                                      .AsEnumerable()
                                      .Select(x => new Product
                                      {
                                          Id= Convert.ToInt32(x[0]),
                                          DisplayName= Convert.ToString(x[1])
                                      })
                                      .GroupBy(y => y.id).ToList();

有人可以建议我如何编写LINQ查询以获得此结果?

更新 我又添加了一个子类并将其添加到主Product类中。见下文:

public class Product
    {
    public int Id {get;set;}
    public string DisplayName{get;set;}
    public Ingredient[] Ingredents{get;set;}
    public Price MyPrice{get;set;}
    }
public class Price
{
    public int min {get;set;}
    public int max {get;set;}
    public int defaultPrice {get;set;}
}

我按如下方式修改了LINQ查询并获得了结果。 我的问题是在LINQ查询下面,我应该写.First<Price>还是.FirstOrDefault<Price>? 这是处理这种情况的正确方法还是有其他办法吗?

var lstProducts = dsGetProducts.Tables[0].AsEnumerable().Cast<DataRow>()
                  .GroupBy(r => new { Id = r["Id"], 
                                      DisplayName = r["DisplayName"], 
                                      priceMax = r["priceMax"],
                                      priceMin = r["priceMin"],
                                      priceDefault = r["priceDefault"]
                                    })
                  .Select(g => new Product()
                  {
                     Id = (int)g.Key.Id,
                     DisplayName = (string)g.Key.DisplayName,
                     Ingredients = g.Select(r => new Ingredient()
                     {
                        id = (int)r["IngredientId"],
                        Name = (string)r["IngName"]
                     }).ToArray(),
                     MyPrice =  g.Select(r => new Price()
                     {
                        min= (int)r["minPrice"],
                        max= (int)r["maxPrice"],
                        defaultPrice= (int)r["priceDefault"],
                     }).FirstOrDefault<Price>()

1 个答案:

答案 0 :(得分:3)

您需要分组,然后项目

dataTable.Rows.Cast<DataRow>()
    .GroupBy(r => new { Id = r["Id"], DisplayName = r["DisplayName"] })
    .Select(g => new Product()
    {
        Id = (int)g.Key.Id,
        DisplayName = (string)g.Key.DisplayName,
        Ingredients = g.Select(r => new Ingredient()
        {
            id = (int)r["IngredientId"],
            Name = (string)r["IngName"]
        }).ToArray()
    });

您需要Cast<DataRow>。自.NET 1.1以来,DataTable已经存在,其中泛型不存在。因此,枚举器产生object个实例。

考虑到评论,如果您使用Field<T>中的System.Data.DataSetExtensions扩展方法安装了.NET Framework 3.5,则可以使用另一个选项。请务必添加对程序集的引用:

dataTable.Rows.Cast<DataRow>()
    .GroupBy(r => new { Id = r.Field<int>("Id"), DisplayName = r.Field<string>("DisplayName") })
    .Select(g => new Product()
    {
        Id = g.Key.Id,
        DisplayName = g.Key.DisplayName,
        Ingredients = g.Select(r => new Ingredient()
        {
            id = r.Field<int>("IngredientId"),
            Name = r.Field<string>("IngName")
        }).ToArray()
    });