ToList Method

Overview

The ToList method converts all rows in a data table into list of elements.

Namespace and Assembly

Namespace: PocoDataSet.Extensions
Assembly: PocoDataSet.Extensions.dll

The first overload

The first overload produces an list of "live" objects. Any change made through the interface is immediately reflected in the underlying data row:

/// <summary>
/// Converts all rows in the specified data table to a list of interface proxies.
/// </summary>
/// <typeparam name="TInterface">The interface type describing the table's row contract.</typeparam>
/// <param name="dataTable">Data table</param>
/// <returns>A list of TInterface proxies backed by data rows.</returns>
public static List<TInterface> ToList<TInterface>(this IDataTable? dataTable) where TInterface : class

Usage Example

Assuming that there is an interface IEmploymentType, which defines employment type functionality:

/// <summary>
// Defines employment type functionality
/// </summary>
public interface IEmploymentType
{
    int Id { get; set; }
    string Code { get; set; }
    string? Description { get; set; }
}

// 1. Create data set
IDataSet dataSet = DataSetFactory.CreateDataSet();

// 2. Add employment type table to data set
IDataTable employmentTypeDataTable = dataSet.AddNewTable("EmploymentType");
employmentTypeDataTable.AddColumn("Id", DataTypeNames.INT32);
employmentTypeDataTable.AddColumn("Code", DataTypeNames.STRING);
employmentTypeDataTable.AddColumn("Description", DataTypeNames.STRING);

// 3. Add several rows to employment type table
IDataRow employmentTypeDataRow1 = employmentTypeDataTable.AddNewRow();
employmentTypeDataRow1["Id"] = 1;
employmentTypeDataRow1["Code"] = "ET01";
employmentTypeDataRow1["Description"] = "Full Time";

IDataRow employmentTypeDataRow2 = employmentTypeDataTable.AddNewRow();
employmentTypeDataRow2["Id"] = 2;
employmentTypeDataRow2["Code"] = "ET02";
employmentTypeDataRow2["Description"] = "Part Time";

// 4. Call ToList method to get live proxies backed by IDataRow
List<IEmploymentType> employmentTypes = employmentTypeDataTable.ToList<IEmploymentType>();

// 5. Change data of the second row through the interface
employmentTypes[1].Description = "Contractor";

The second overload

The second overload produces either "live" or detached results, depending entirely on what the selector delegate returns.

/// <summary>
/// Converts all rows in the specified data table to an list of elements using a custom selector.
/// </summary>
/// <typeparam name="T">The element type of the resulting list.</typeparam>
/// <param name="dataTable">Data table</param>
/// <param name="selector">A delegate that creates an element of specified type from a data row.</param>
/// <returns>An list of elements created from each row.</returns>
public static List<T> ToList<T>(this IDataTable? dataTable, Func<IDataRow, T> rowSelectionFunction)

Usage example. Case 1 – Live result: selector returns an interface proxy

If the selector returns an interface proxy created from the row (for example, via AsInterface<TInterface>()), the resulting list contains objects backed by IDataRow. Setting a property updates the underlying row immediately.

// 1. Create data set
IDataSet dataSet = DataSetFactory.CreateDataSet();

// 2. Add employment type table to data set
IDataTable employmentTypeDataTable = dataSet.AddNewTable("EmploymentType");
employmentTypeDataTable.AddColumn("Id", DataTypeNames.INT32);
employmentTypeDataTable.AddColumn("Code", DataTypeNames.STRING);
employmentTypeDataTable.AddColumn("Description", DataTypeNames.STRING);

// 3. Add several rows to employment type table
IDataRow employmentTypeDataRow1 = employmentTypeDataTable.AddNewRow();
employmentTypeDataRow1["Id"] = 1;
employmentTypeDataRow1["Code"] = "ET01";
employmentTypeDataRow1["Description"] = "Full Time";

IDataRow employmentTypeDataRow2 = employmentTypeDataTable.AddNewRow();
employmentTypeDataRow2["Id"] = 2;
employmentTypeDataRow2["Code"] = "ET02";
employmentTypeDataRow2["Description"] = "Part Time";

// 4. Call ToList method providing the selector to get live proxies backed by IDataRow
List<IEmploymentType> employmentTypes = employmentTypeDataTable.ToList(row => row.AsInterface<IEmploymentType>());

// 5. Change data of the second row through the interface
employmentTypes[1].Description = "Contractor";

Usage example. Case 2 – Live result: selector returns the IDataRow itself

If the selector returns IDataRow (or another row-backed wrapper), the result is live because you still hold direct references to the rows in the table.

// 1. Create data set
IDataSet dataSet = DataSetFactory.CreateDataSet();

// 2. Add employment type table to data set
IDataTable employmentTypeDataTable = dataSet.AddNewTable("EmploymentType");
employmentTypeDataTable.AddColumn("Id", DataTypeNames.INT32);
employmentTypeDataTable.AddColumn("Code", DataTypeNames.STRING);
employmentTypeDataTable.AddColumn("Description", DataTypeNames.STRING);

// 3. Add several rows to employment type table
IDataRow employmentTypeDataRow1 = employmentTypeDataTable.AddNewRow();
employmentTypeDataRow1["Id"] = 1;
employmentTypeDataRow1["Code"] = "ET01";
employmentTypeDataRow1["Description"] = "Full Time";

IDataRow employmentTypeDataRow2 = employmentTypeDataTable.AddNewRow();
employmentTypeDataRow2["Id"] = 2;
employmentTypeDataRow2["Code"] = "ET02";
employmentTypeDataRow2["Description"] = "Part Time";

// 4. Call ToList method providing the selector to get table rows
List<IDataRow> rows = employmentTypeDataTable.ToList(row => row);

// 5. Change data of the second row
rows[1]["Description"] = "Contractor";

Usage example. Case 3 – Detached result: selector returns a new object (snapshot)

If the selector creates a new object (for example, a DTO/POCO) and copies values from the row, the resulting list is a snapshot. Changing the returned objects does not affect the table, and later table changes are not reflected in the returned objects.

Assuming that there is a class which implements interface IEmploymentType:

/// <summary>
// Provides employment type functionality
/// </summary>
public class EmploymentType : IEmploymentType
{
    public int Id { get; set; }
    public string Code { get; set; }
    public string? Description { get; set; }
}

// 1. Create data set
IDataSet dataSet = DataSetFactory.CreateDataSet();

// 2. Add employment type table to data set
IDataTable employmentTypeDataTable = dataSet.AddNewTable("EmploymentType");
employmentTypeDataTable.AddColumn("Id", DataTypeNames.INT32);
employmentTypeDataTable.AddColumn("Code", DataTypeNames.STRING);
employmentTypeDataTable.AddColumn("Description", DataTypeNames.STRING);

// 3. Add several rows to employment type table
IDataRow employmentTypeDataRow1 = employmentTypeDataTable.AddNewRow();
employmentTypeDataRow1["Id"] = 1;
employmentTypeDataRow1["Code"] = "ET01";
employmentTypeDataRow1["Description"] = "Full Time";

IDataRow employmentTypeDataRow2 = employmentTypeDataTable.AddNewRow();
employmentTypeDataRow2["Id"] = 2;
employmentTypeDataRow2["Code"] = "ET02";
employmentTypeDataRow2["Description"] = "Part Time";

// 4. Call ToList method providing the selector to get stand alone POCOs
List<EmploymentType> employmentTypes = employmentTypeDataTable.ToList(row => row.ToPoco<EmploymentType>());

// Case 1: Row field value does not change if POCO property changes
employmentTypes[0].Description = "Contractor";

// Case 2: POCO property does not change if row field value changes
employmentTypeDataTable.Rows[1]["Description"] = "Contractor";

 

Table of Content POCO DataSet DataTable Extensions Group DataTable Members

 


Business Process Programming in .Net
© 2004–2026 Laskarzhevsky Software Inc.
Unless otherwise noted, the content of this website is licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).
Code examples are provided under the MIT License.
You are free to share and adapt the material provided that appropriate credit is given and any modifications are clearly indicated.
The information provided on this website is for educational purposes only.
The author and publisher make no warranties regarding the completeness or suitability of the information and are not responsible for any damages resulting from its use.