我需要从我从另一个系统接收的DataTable生成一个'IEnumerable。以下代码适用于ASP.NET 4.6.1。
public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable)
{
var data = dataTable.AsEnumerable().Select(row =>
new UserAssignmentDto
{
Id = ((string)row["AssignmentNumber"]),
Position = (string) row["EsrPositionTitle"],
});
return data;
}
但是,'DataTable'不再包含ASP.NET Core 2.0中'AsEnumerable'的定义。
生成我需要的'IEnumerable'的最有效方法是什么?
答案 0 :(得分:7)
这是一个通用的AsEnumerable扩展函数,用于模仿经典的AsEnumerable()所做的事情,并从DataTable返回一个DataRows的Enumerable集合。对于希望在将代码移植到.net核心时尽量减少重构量的人很有用。
public static IEnumerable<DataRow> AsEnumerable(this DataTable table)
{
for (int i = 0; i < table.Rows.Count; i++)
{
yield return table.Rows[i];
}
}
答案 1 :(得分:3)
AsEnumerable()在.NET Core 2.0中确实存在,您只需要添加对System.Data.DataExtensions的引用,如对类似问题的回答中所述。 LINQ to DataSet, DataTable.AsEnumerable() not recognized
答案 2 :(得分:2)
您可以做的最有效的事情之一就是自己编写迭代代码,使用for循环而不是LINQ,只需迭代DataTable行并构建/补充IEnumerable<UserAssignmentDto>
方法返回值“手”。
由于DataTable没有在.NET Core 2.0中实现Enumerator,因此您需要使用“常规”for
循环来迭代行。您无法使用foreach
,因为DataTable尚未在.NET Core 2.0中实现IEnumerable。
public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable)
{
var retList = new List<UserAssignmentDto>();
for(int i = 0; i < dataTable.Rows.Count; i++)
{
var row = dataTable.Rows[i];
var temp = new UserAssignmentDto(){
Id = row["AssignmentNumber"],
Position = row["EsrPositionTitle"]
};
retList.Add(temp);
}
return retList;
}
答案 3 :(得分:2)
不是最有效的,但作为替代方案,您可以使用Select
方法:
DataRow[] rows= dataTable.Select();
现在你有一个IEnumerable行。 这种方法可以帮助某人:
public static List<T> ConvertDataTableToGenericList<T>(DataTable dt)
{
var columnNames = dt.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName)
.ToList();
var properties = typeof(T).GetProperties();
DataRow[] rows= dataTable.Select();
return rows.Select(row =>
{
var objT = Activator.CreateInstance<T>();
foreach (var pro in properties)
{
if (columnNames.Contains(pro.Name))
pro.SetValue(objT, row[pro.Name]);
}
return objT;
}).ToList();
}
答案 4 :(得分:1)
效率取决于用例。如果您需要整个结果,Brians的答案是好的。可以通过预先分配List的容量以避免调整大小或更改为Array来改进它,但通常它是好的。我宁愿返回List或Array来更明确地显示它的作用,但这是我个人的选择。它在被调用时保留了DataTable的状态,这可能是好的还是坏的,这取决于你需要什么。
如果有可能你不需要所有项目,或者你根本不会枚举IEnumerable,那么构建真正的枚举器可能更有效:
public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable)
{
foreach (DataRow row in dataTable)
{
yield return new UserAssignmentDto()
{
Id = row["AssignmentNumber"],
Position = row["EsrPositionTitle"]
};
}
}
但它仍然不是最快的选择。您可以避免每次产生时分配新对象。您可以每次返回相同的对象,只需相应地设置属性即可。它有一个明显的缺点,你不能存储来自这种IEnumerable的对象以备将来使用,但有时你不需要它。
public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable)
{
UserAssignmentDto ret = new UserAssignmentDto();
foreach (DataRow row in dataTable)
{
ret.Id = row["AssignmentNumber"];
ret.Position = row["EsrPositionTitle"];
yield return ret;
}
}
答案 5 :(得分:1)
.net核心2的正确nuget软件包是System.Data.DataSetExtensions
答案 6 :(得分:1)
您可以使用myDataTable.Select();
返回所有DataRow的数组