[c#] Convert DataTable to IEnumerable<T>

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.

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to datatable

Can't bind to 'dataSource' since it isn't a known property of 'table' How to get a specific column value from a DataTable in c# Change Row background color based on cell value DataTable How to bind DataTable to Datagrid Find row in datatable with specific id Datatable to html Table How to Edit a row in the datatable How do I use SELECT GROUP BY in DataTable.Select(Expression)? How to fill a datatable with List<T> SqlBulkCopy - The given value of type String from the data source cannot be converted to type money of the specified target column

Examples related to ienumerable

How to concatenate two IEnumerable<T> into a new IEnumerable<T>? Remove an item from an IEnumerable<T> collection Converting from IEnumerable to List Shorter syntax for casting from a List<X> to a List<Y>? filtering a list using LINQ How to check if IEnumerable is null or empty? Convert from List into IEnumerable format IEnumerable vs List - What to Use? How do they work? Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.IEnumerable<> Convert DataTable to IEnumerable<T>