我正在从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
?
答案 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);
答案 1 :(得分:2)
如果我理解你的问题,T可以是多种类型。
例如,第一行可以是Person,第二行可以是Dog吗?或者你的意思是不同的类型如string,int,date等(值类型)。
无论您需要创建“T”实体来表示数据表中的数据并进行映射。
您正在寻找的可能是一个映射器,例如ValueInjector或Automapper。
甚至map manually:
This answer此处显示了如何使用ValueInjector将DataTable映射到类。它可以给你一个开端。
我希望这会有所帮助。
答案 2 :(得分:1)
@Douglas Jimenez有一个相关的问题。如果仅type
变化,则可以使用公共字段的接口(或没有字段的对象)和实现其他字段的不同类型轻松解决此问题。在构建列表时,然后使用工厂决定为行(或者wholde DataTable)构建哪种类型,然后使用该行构建对象。
但是,如果在编译时不知道类型,则有许多解决方案:
dynamic
关键字一起使用。
ExpandoObject
可能会满足您的需求。Dictionary<string, object>
)Emit
框架发出类型。
也可能有其他解决方案。祝你选择的解决方案好运。
答案 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)
我遇到了这个问题并且使用了
中的代码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;
}
}