将DataTable转换为List <t>,其中List of List是Dynamic </t>

时间:2013-12-30 10:17:38

标签: c# list datatable

我正在从C#代码执行存储过程

private void DataToGrid()
{
    DataTable dt = new DataTable();
    string[,] aryPara = new string[,] 
    {{ "@pClassId", "10" } ,
    { "@pMediumId", "11" } ,
    { "@pStreamId", "12" } ,
    { "@pSessionId","13" } ,
    { "@pSectionId", "15" } ,
    { "@pShiftId", "16" } ,
    { "@pDateId", "17" } };

    dt = CallStoredProcedureUsingAdapterFillDataTabel("ssspAtdDailyattendance", aryPara);  
    DatagridView1.DataSource = dt;
}

public DataTable CallStoredProcedureUsingAdapterFillDataTabel(string StoredProcedureName, [Optional] string[,] aryParameters)
{
    SqlConnection con = new SqlConnection();
    con.ConnectionString = "Data Source=AIS-OCTACORE\SQLserver2008r2;Initial Catalog= SchoolSoulDataTest; integrated security=SSPI";
    con.open();
    SqlCommand lSQLCmd = new SqlCommand();
    SqlDataAdapter adp = new SqlDataAdapter();
    DataTable dt = new DataTable();
    lSQLCmd.CommandType = CommandType.StoredProcedure;
    lSQLCmd.CommandText = StoredProcedureName;
    lSQLCmd.CommandTimeout = 300;
    try
    {
        for (int i = 0; i < aryParameters.GetLength(0); i++)
        {
            lSQLCmd.Parameters.Add(new SqlParameter(aryParameters[i, 0], aryParameters[i, 1]));
        }
    }
    catch (Exception ex)
    {

    }
    lSQLCmd.Connection = con;
    adp.SelectCommand = lSQLCmd;
    adp.Fill(dt);
    clsConnectionClose();
    return dt;
}

其中ssspAtdDailyattendance是动态存储过程,其中存储过程返回的数据具有可变数量的列。

现在我想将DataTable dt转换为List<T>但是dt返回可变数量的列,因此T的类型不固定

所以我的问题是如何将dt转换为List

5 个答案:

答案 0 :(得分:2)

我建议您使用 Dapper ,而不是自己编写和维护样板代码。 Dapper支持dynamic个对象。

  

执行查询并将其映射到动态对象列表

public static IEnumerable<dynamic> Query (this IDbConnection cnn, string sql, 
object param = null, SqlTransaction transaction = null, bool buffered = true)
  

此方法将执行SQL并返回动态列表。

     

使用示例:

var rows = connection.Query("select 1 A, 2 B union all select 3, 4");

((int)rows[0].A).IsEqualTo(1);    
((int)rows[0].B).IsEqualTo(2);    
((int)rows[1].A).IsEqualTo(3);   
((int)rows[1].B).IsEqualTo(4);

网站:http://code.google.com/p/dapper-dot-net/

NuGet:http://www.nuget.org/packages/Dapper/

答案 1 :(得分:2)

如果我理解你的问题,T可以是多种类型。

例如,第一行可以是Person,第二行可以是Dog吗?或者你的意思是不同的类型如string,int,date等(值类型)。

无论您需要创建“T”实体来表示数据表中的数据并进行映射。

您正在寻找的可能是一个映射器,例如ValueInjector或Automapper。

甚至map manually

This answer此处显示了如何使用ValueInjector将DataTable映射到类。它可以给你一个开端。

我希望这会有所帮助。

答案 2 :(得分:1)

@Douglas Jimenez有一个相关的问题。如果仅type变化,则可以使用公共字段的接口(或没有字段的对象)和实现其他字段的不同类型轻松解决此问题。在构建列表时,然后使用工厂决定为行(或者wholde DataTable)构建哪种类型,然后使用该行构建对象。

但是,如果在编译时不知道类型,则有许多解决方案:

  • 将DLR与dynamic关键字一起使用。
    • ExpandoObject可能会满足您的需求。
  • 使用散列图(如Dictionary<string, object>
  • 使用Emit框架发出类型。
    • 此解决方案实际上很复杂,会引导您进入CLR的高级部分。但是,这非常有效。
    • 如果您选择此路径,此tutorial将对您有所帮助。
    • 根据您的需要,这可能矫枉过正

也可能有其他解决方案。祝你选择的解决方案好运。

答案 3 :(得分:0)

根据sll发布的回答,您可以使用类似

的内容
IList<Class1> items = dt.AsEnumerable().Select(row => 
    new Class1
        {
            id = row.Field<string>("id"),
            name = row.Field<string>("name")
        }).ToList();

但是既然你要求它可能包含不同的列,那么你可以拥有一个包含所有属性的公共类,并在获取列之前进行检查,

public class Class1
{
    private int id;
    public string name;

    public Class1(DataRow row)
    {
        id = (int)GetColumnValue(row, "id");
        name = (string)GetColumnValue(row, "name");
    }

    public object GetColumnValue(DataRow row, string column)
    {
        return row.Table.Columns.Contains(column) ? row[column] : null;
    }
}

然后你可以调用函数as,

IList<Class1> items = dt.AsEnumerable().Select(row => new Class1(row)).ToList();

答案 4 :(得分:-1)

我遇到了这个问题并且使用了

中的代码
  

http://musthaan.com/2016/01/18/datatable-to-dynamic-list/

public static class HelperExtensions
{
  public static List<dynamic> ToDynamic(this DataTable dt)
  {
    var dynamicDt = new List<dynamic>();
    foreach (DataRow row in dt.Rows)
    {
      dynamic dyn = new ExpandoObject();
      dynamicDt.Add(dyn);
      foreach (DataColumn column in dt.Columns)
      {
         var dic = (IDictionary<string, object>)dyn;
         dic[column.ColumnName] = row[column];
      }
    }
    return dynamicDt;
  }
}