Convert DataTable to IEnumerable

前端 未结 8 1580
梦毁少年i
梦毁少年i 2020-11-29 22:50

I am trying to convert a DataTable to an IEnumerable. Where T is a custom type I created. I know I can do it by creating a List but I was thinking if t

相关标签:
8条回答
  • 2020-11-29 23:42

    If you are producing the DataTable from an SQL query, have you considered simply using Dapper instead?

    Then, instead of making a SqlCommand with SqlParameters and a DataTable and a DataAdapter and on and on, which you then have to laboriously convert to a class, you just define the class, make the query column names match the field names, and the parameters are bound easily by name. You already have the TankReading class defined, so it will be really simple!

    using Dapper;
    
    // Below can be SqlConnection cast to DatabaseConnection, too.
    DatabaseConnection connection = // whatever
    IEnumerable<TankReading> tankReadings = connection.Query<TankReading>(
       "SELECT * from TankReading WHERE Value = @value",
       new { value = "tank1" } // note how `value` maps to `@value`
    );
    return tankReadings;
    

    Now isn't that awesome? Dapper is very optimized and will give you darn near equivalent performance as reading directly with a DataAdapter.

    If your class has any logic in it at all or is immutable or has no parameterless constructor, then you probably do need to have a DbTankReading class (as a pure POCO/Plain Old Class Object):

    // internal because it should only be used in the data source project and not elsewhere
    internal sealed class DbTankReading {
       int TankReadingsID { get; set; }
       DateTime? ReadingDateTime { get; set; }
       int ReadingFeet { get; set; }
       int ReadingInches { get; set; }
       string MaterialNumber { get; set; }
       string EnteredBy { get; set; }
       decimal ReadingPounds { get; set; }
       int MaterialID { get; set; }
       bool Submitted { get; set; }
    }
    

    You'd use that like this:

    IEnumerable<TankReading> tankReadings = connection
       .Query<DbTankReading>(
          "SELECT * from TankReading WHERE Value = @value",
          new { value = "tank1" } // note how `value` maps to `@value`
       )
       .Select(tr => new TankReading(
          tr.TankReadingsID,
          tr.ReadingDateTime,
          tr.ReadingFeet,
          tr.ReadingInches,
          tr.MaterialNumber,
          tr.EnteredBy,
          tr.ReadingPounds,
          tr.MaterialID,
          tr.Submitted
       });
    

    Despite the mapping work, this is still less painful than the data table method. This also lets you perform some kind of logic, though if the logic is any more than very simple straight-across mapping, I'd put the logic into a separate TankReadingMapper class.

    0 讨论(0)
  • 2020-11-29 23:44
            PagedDataSource objPage = new PagedDataSource();
    
            DataView dataView = listData.DefaultView;
            objPage.AllowPaging = true;
            objPage.DataSource = dataView;
            objPage.PageSize = PageSize;
    
            TotalPages = objPage.PageCount;
    
            objPage.CurrentPageIndex = CurrentPage - 1;
    
            //Convert PagedDataSource to DataTable
            System.Collections.IEnumerator pagedData = objPage.GetEnumerator();
    
            DataTable filteredData = new DataTable();
            bool flagToCopyDTStruct = false;
            while (pagedData.MoveNext())
            {
                DataRowView rowView = (DataRowView)pagedData.Current;
                if (!flagToCopyDTStruct)
                {
                    filteredData = rowView.Row.Table.Clone();
                    flagToCopyDTStruct = true;
                }
                filteredData.LoadDataRow(rowView.Row.ItemArray, true);
            }
    
            //Here is your filtered DataTable
            return filterData; 
    
    0 讨论(0)
提交回复
热议问题