Edward Edward - 24 days ago 12
C# Question

Convert DataTable to nestead Class by linq

I have a nested class definition as below:

[XmlRoot()]
public class cars
{
[XmlElement(ElementName="car")]
public car[] carList { get; set; }
}
public class car
{
[XmlElement(ElementName = "manufacture")]
public string manufacture { get; set; }
[XmlElement(ElementName = "models")]
public models modelList { get; set; }
}
public class models
{
[XmlElement(ElementName = "model")]
public model[] modelList { get; set; }
}
public class model
{
[XmlElement(ElementName = "name")]
public string name { get; set; }
[XmlElement(ElementName = "color")]
public string color { get; set; }
}


I have a DataTable as below:

DataTable dt = new DataTable();
dt.Columns.Add("Manufacture");
dt.Columns.Add("ModelName");
dt.Columns.Add("Color");

Object[] rows = {
new Object[]{"P1","405","1,6"},
new Object[]{"P1","406","1,7"},
new Object[]{"P2","407","1,8"},
new Object[]{"P2","408","1,9"}
};
dt.Rows.Add(rows);


I want to convert my data in DataTable to my class cars.
Any help would be appreciated.

Update:
For using suggestion, I need to change Rows.Add with below code, otherwise, I will only get object in result.

DataRow dr= dt.NewRow();
dr["Manufacture"] = "Peugeot1";
dr["ModelName"] = "405";
dr["Color"] = "1,6";
dt.Rows.Add(dr);
DataRow dr2 = dt.NewRow();
dr2["Manufacture"] = "Peugeot1";
dr2["ModelName"] = "406";
dr2["Color"] = "1,7";
dt.Rows.Add(dr2);
DataRow dr3 = dt.NewRow();
dr3["Manufacture"] = "Peugeot2";
dr3["ModelName"] = "405";
dr3["Color"] = "1,6";
dt.Rows.Add(dr3);

Answer

Use GroupBy to group all the rows by the Manufacture and then for each group project a new Car. To populate the ModelList property use a Select on the group:

var result = (from row in dt.AsEnumerable()
              group row by row.Field<string>("Manufacture") into grouping
              select new Car
              {
                  Manufacture = grouping.Key,
                  ModelList = grouping.Select(item => new Model
                  {
                      Name = item.Field<string>("ModelName"),
                      Color = item.Field<string>("Color")
                  }).ToArray()
              }).ToList();

You can also use the method syntax with the GroupBy overload where you specify a selector predicate:

var result = dt.AsEnumerable()
               .GroupBy(row => row.Field<string>("Manufacture"),
                        row => new Model
                        {
                            Name = row.Field<string>("ModelName"),
                            Color = row.Field<string>("Color")
                        })
               .Select(group => new Car
               {
                   Manufacture = group.Key,
                   ModelList = group.ToArray()
               }).ToList();

Note that I have change the classes and property names to match the C# naming conventions