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

Posted

技术标签:

【中文标题】在 ASP.NET Core 2.0 中将 DataTable 转换为 IEnumerable<T>【英文标题】:Convert DataTable to IEnumerable<T> in ASP.NET Core 2.0 【发布时间】:2018-02-04 15:47:43 【问题描述】:

我需要从一个 DataTable 中生成一个 'IEnumerable,该 DataTable 作为来自另一个系统的输入。以下代码在 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;
    

但是,在 ASP.NET Core 2.0 中,“DataTable”不再包含“AsEnumerable”的定义。

生成我需要的“IEnumerable”的最有效方法是什么?

【问题讨论】:

使用 for 循环并遍历 DataTable 行并水合 IEnumerable 你能告诉我你所说的水合物是什么意思吗? 你不能直接说dataTable.Rows.Select(...); 吗?如果选择“项目”是一个对象,你可以添加 OfType dataTable.Rows.OfType&lt;DataRow&gt;().Select(...); 您也可以使用演员表:dataTable.Rows.Cast&lt;DataRow&gt;().Select(...)。这比 OfType 好还是坏? 【参考方案1】:

.net core 2 的正确 nuget 包是 System.Data.DataSetExtensions

【讨论】:

这个nuget是后面介绍的;但真的很有帮助,因为我们可以像 .net 框架一样使用。 :)【参考方案2】:

这是一个通用的 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];
        
    

【讨论】:

【参考方案3】:

不是最有效的,但作为替代方案,您可以使用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= dt.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】:

您可以做的最有效的事情之一是自己编写迭代代码,使用 for 循环而不是 LINQ,只需迭代 DataTable 行并“手动”构建/水合 IEnumerable&lt;UserAssignmentDto&gt; 方法返回值.

由于 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;

【讨论】:

我认为 List 需要初始化。此外,我收到错误 CS1579 foreach 语句无法对“DataTable”类型的变量进行操作,因为“DataTable”不包含“GetEnumerator”的公共定义 @RoddyBalkan 好的,我更新了答案以修复该错误 @RoddyBalkan List 已经初始化,这行代码: var retList = List(); @RoddyBalkan 对不起,我忘记了初始化 List 的新关键字,请注意,您不能使用 foreach,因为 DataTable 在 .NET Core 2.0 中没有实现 GetEnumerator【参考方案5】:

AsEnumerable() 确实存在于 .NET Core 2.0 中,您只需添加对 System.Data.DataExtensions 的引用,如类似问题的答案中所述。 LINQ to DataSet, DataTable.AsEnumerable() not recognized

【讨论】:

【参考方案6】:

效率取决于用例。如果您需要整个结果,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;
            
        

【讨论】:

【参考方案7】:

你可以使用myDataTable.Select();它返回一个包含所有DataRow的数组

【讨论】:

以上是关于在 ASP.NET Core 2.0 中将 DataTable 转换为 IEnumerable<T>的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core 2.0 自动化发布和部署(Centos7 & Docker & Jenkins )

带你做 WebAPI 迁移 ASP.NET Core 2.0

ASP.Net Core 2.0 FileTable 使用

ASP.NET Core 2.0中的HttpContext

ASP.NET CORE 2.0 中的 FromUri

ASP.NET Core 2.0 新特性全新体验