0

I am trying to use the function found here: DataTable to List<object>

  public static IList<T> ConvertTo<T>(DataTable table)
        {
            if (table == null)
                return null;

            List<DataRow> rows = new List<DataRow>();

            foreach (DataRow row in table.Rows)
                rows.Add(row);

            return ConvertTo<T>(rows);
        }

the return statement is giving me an exception stating:

The best overloaded method match for 'Utilities.Utility.ConvertTo<T>(System.Data.DataTable)' has some invalid arguments

Can someone help me fix this error??

Community
  • 1
  • 1
Nick LaMarca
  • 8,076
  • 31
  • 93
  • 152

2 Answers2

1

Don't do it that way use Marc's amazing function ( https://stackoverflow.com/a/545429/215752 ) I mean really... that is exactly what you want.. right?


You need another function

public static IList<T> ConvertTo<T>(IList<DataRow> rows)
    {
        IList<T> list = null;

        if (rows != null)
        {
            list = new List<T>();

            foreach (DataRow row in rows)
            {
                T item = CreateItem<T>(row);
                list.Add(item);
            }
        }

        return list;
    }

The question you link had a link in it. I'd suggest looking there for more info:

http://lozanotek.com/blog/archive/2007/05/09/Converting_Custom_Collections_To_and_From_DataTable.aspx

There you will find all the code, which I expect will compile. I won't vouch for the reliability or reasonably of using it however.

Community
  • 1
  • 1
Hogan
  • 69,564
  • 10
  • 76
  • 117
1

First, you are returning a T but not a IList<T>. Secondly, how are you expecting a DataRow to be converted to an unknown T, especially if a row has several columns?

Try something like this

public static IList<IList<T>> ConvertTo<T>(DataTable table)
{
    if (table == null)
        return null;
    List<IList<T>> rows = new List<IList<T>>();
    foreach (DataRow row in table.Rows) {
        rows.Add(row.ItemArray.Cast<T>().ToArray());
    }
    return rows;
}

UPDATE:

A custom object is something like this

public class Employee
{
    public int ID { get; set; }
    public string Name { get; set; }
    public decimal Salary { get; set; }
}

However, in that case a generic interface is not useful, since you would have to code for that specific class

public static IList<Employee> GetEmployees(DataTable table)
{
    var employees = new List<Employee>();
    if (table != null) {
        foreach (DataRow row in table.Rows) {
            var emp = new Employee();
            emp.ID = (int)row["ID"];
            emp.Name = (string)row["Name"];
            emp.Salary = (decimal)row["Salary"];
            employees.Add(emp);
        }
    }
    return employees;
}

This code has to be different for different tables and cannot be generic. At least not without using Reflection and assuming that the properties have the same names as the table columns.


A solution not using some tricky Reflection code or other magic tricks would be to define an interface like this

public interface IDataObject
{
    void FillFromRow(DataRow row);
}

Then you declare Employee or any other data classes like this

public class Employee : IDataObject
{
    public int ID { get; set; }
    public string Name { get; set; }
    public decimal Salary { get; set; }

    public void FillFromRow(DataRow row)
    {
        ID = (int)row["ID"];
        Name = (string)row["Name"];
        Salary = (decimal)row["Salary"];
    }
}

Now you can use generics again

public static IList<T> GetItems<T>(DataTable table)
    where T : IDataObject, new()
{
    var items = new List<T>();
    if (table != null) {
        foreach (DataRow row in table.Rows) {
            T item = new T();
            item.FillFromRow(row);
            items.Add(item);
        }
    }
    return items;
}
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • @Oliver can you show me a sample of how to use that function if i want to convert the datatable to an IList? – Nick LaMarca Mar 16 '12 at 18:54
  • @Oliver this is how i coded it but others say (decimal)row["Salary"]; if considered "bad" coding practice. whats your opinion? – Nick LaMarca Mar 16 '12 at 19:10
  • Who says that is bad coding practice? Please give a reference. – Hogan Mar 16 '12 at 19:19
  • `DataRow` returns column values as `object`. You just have to cast them. A very efficient way to read data from db tables is to use a `DataReader`. `DataReader` has typed methods to get values like `int i = reader.GetInt32("ID");` – Olivier Jacot-Descombes Mar 16 '12 at 19:36
  • if i change the field name in the database from "ID" to "MyID" I would have to change "ID" in all places all over the code. – Nick LaMarca Mar 16 '12 at 21:27
  • Only where you specify the column name in the DataRow `ID = (int)row["MyID"];`. Your property in the custom object can have a different name. – Olivier Jacot-Descombes Mar 16 '12 at 22:13