在ASP.NET Core 2.0中将DataTable转换为IEnumerable <t>

时间:2017-08-27 01:22:16

标签: c# asp.net linq asp.net-core

我需要从我从另一个系统接收的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'的最有效方法是什么?

7 个答案:

答案 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的数组