Converting recordsets to POCO The goal this method was to emulate the way EF or Dapper return to you concrete POCO classes instead of recordsets when querying your db. Our current code is riddled with iterations over recordsets and I want to consolidate to an extension method that can convert the recordset into an Enumerable&lt;T&gt;.

Review

I'm concerned about how efficient this will be. When querying the db for a single or handful of records I'm not concerned but we sometimes query for an entire table (i.e. ~100,000 records) and in that case will the iterations in this start to cause performance issues? Is there a better way to resolve the recordsets to classes without iterating? Any other constructive remarks appreciated.

public static IEnumerable&lt;T&gt; AsList&lt;T&gt;(this Recordset rs) where T : new()
{
    IEnumerable&lt;PropertyInfo&gt; props = new List&lt;PropertyInfo&gt;(typeof(T).GetProperties()).Where(p =&gt; p.CanWrite);
    List&lt;T&gt; results = new List&lt;T&gt;();
    while (!rs.Eof)
    {
        T obj = new T();
        foreach (PropertyInfo property in props)
        {
            var val = rs[property.Name].Value;
            if (val != null) property.SetValue(obj, Convert.ChangeType(val, property.PropertyType));

        }
        rs.MoveNext();

        results.Add(obj);
    }

    return results.AsEnumerable();
}


used as...

Recordset rs = new Recordset();
rs.Open("select * from Users", connection)
IEnumerable&lt;User&gt; results = rs.AsList&lt;User&gt;();


Post Review Update

After great feedback from Heslacher and t3chb0t the following code has been finalized. Note there was a change in the requirements and sister method was created As&lt;T&gt;() to create a single class instance from a recordset. The feedback from the review has been applied to it as well.

public static IList&lt;T&gt; AsList&lt;T&gt;(this Recordset rs) where T : class, new()
{
    var results = new List&lt;T&gt;();

    if (rs == null) throw new ArgumentNullException("rs");
    if (rs.Eof) return results;

    IList&lt;PropertyInfo&gt; properties = GetProperties&lt;T&gt;();

    while (!rs.Eof)
    {
        results.Add(CreateInstance&lt;T&gt;(properties, rs));
        rs.MoveNext();
    }

    return results;
}


public static T As&lt;T&gt;(this Recordset rs) where T : class, new()
{
    if (rs.Eof) return default(T);
    IList&lt;PropertyInfo&gt; properties = GetProperties&lt;T&gt;();

    return CreateInstance&lt;T&gt;(properties, rs);
}

private static T CreateInstance&lt;T&gt;(IEnumerable&lt;PropertyInfo&gt; properties, Recordset rs) where T : new()
{
    T obj = new T();
    foreach (PropertyInfo property in properties)
    {
        var val = rs[property.Name].Value;
        if (val != null &amp;&amp; !Convert.IsDBNull(val)) property.SetValue(obj, Convert.ChangeType(val, property.PropertyType));
    }

    return obj;
}

private static IList&lt;PropertyInfo&gt; GetProperties&lt;T&gt;()
{
    return new List&lt;PropertyInfo&gt;(typeof(T).GetProperties().Where(p =&gt; p.CanWrite));
}
public static IEnumerable&lt;T&gt; AsList&lt;T&gt;(this Recordset rs) where T : new()
{
    ..
    List&lt;T&gt; results = new List&lt;T&gt;();
    ..   
    return results.AsEnumerable();
}



This might be very inefficient because when I see that a method returns an IEnumerable&lt;T&gt; I assume its execution is deferred so I automatically do AsList(..).ToList() to execute it but what it actually does, is to iterate the list twice. First time to create the first list and then to create the second list. You should either create a real deferred method or return the List&lt;T&gt; so there is no doubt about the result.




IEnumerable&lt;PropertyInfo&gt; props = new List&lt;PropertyInfo&gt;(typeof(T).GetProperties()).Where(p =&gt; p.CanWrite);



You are executing this Where query for each record because the list wrapps only the GetProperties part (which is an array anyway so I don't understand why you convert it into a list in the first place - linq can work with arrays). You need to call the ToList extension after the Where

var properties = typeof(T).GetProperties().Where(p =&gt; p.CanWrite).ToList();




I also suggest moving the object creation into a separate method so that you don't have any nested loops like this:

public static IEnumerable&lt;T&gt; AsList&lt;T&gt;(this Recordset rs) where T : new()
{
    var properties = typeof(T).GetProperties().Where(p =&gt; p.CanWrite).ToList();
    while (!rs.Eof)
    {
        yield return CreateInstance&lt;T&gt;(properties, rs);        
        rs.MoveNext();
    }
}

private static T CreateInstance&lt;T&gt;(IEnumerable&lt;PropertyInfo&gt; properties, Row row) where T : new()
{
    var obj = new T();
    foreach (var property in properties)
    {
        var value = row[property.Name].Value;
        if (value != null) property.SetValue(obj, Convert.ChangeType(value, property.PropertyType));
    }
    return obj;
}