2011-11-17 78 views
2

我刚刚遇到了DbEnumerator类,它自.NET 1.x起存在,主要用于数据绑定支持。 Reflector揭示了它在内部维护一个用于查找字段名称的Hashtable,因此在迭代大型结果集并按名称访问字段时可能会更高效。有没有人使用DbEnumerator

我遍历一个IDataReader时经常使用以下模式:

// Factory method to create entity from IDataRecord 
private static MyEntity GetMyEntityFromRecord(IDataRecord record) 
{ 
    return new MyEntity(
     (string) record["Field1"] 
     , ... 
    ); 
} 

// Extension method to enumerate an IDataReader 
static IEnumerable<IDataRecord> Enumerate(this IDataReader reader) 
{ 
    foreach(IDataRecord record in reader) 
    { 
     yield return record; 
    } 
} 

IList<MyEntity> GetMyEntities(...) 
{ 
    ... 
    using(IDataReader reader = ...) 
    { 
     return reader.Enumerate().Select(x => GetMyEntityFromRecord(x)).ToList(); 
    } 
    ... 
} 

它似乎在我的Enumerate方法使用DbEnumerator我会得到免费的缓存字段名称查找表:

static IEnumerable<IDataRecord> Enumerate(this IDataReader reader) 
{ 
    DbEnumerator dbEnumerator = new DbEnumerator(reader); 
    while (dbEnumerator.MoveNext()) 
    { 
     yield return (IDataRecord) dbEnumerator.Current; 
    } 
} 

对于在一般情况下DbEnumerator是否可能有益或是否有任何意见?初看起来,它看起来很有吸引力,尽管它是一个旧的.NET 1.x实现(返回一个非泛型枚举器;在内部使用Hashtable而不是通用字典),因为这意味着不再需要按索引访问字段性能的原因。

在每次迭代中实例化DataRecordInternal实例都会产生内部开销,这在某些情况下可能会超过缓存字段名称查找的好处。

回答

0

我决定,这是对最惊喜的原则,以具有延伸方法Enumerate()是默默包装了一个内部的DbEnumerator读者。所以我用一个重载实现了它,允许调用者明确地选择使用DbEnumerator。下一次我玩大型结果集时,我可能会尝试做一些基准测试。

public static IEnumerable<IDataRecord> Enumerate(this IDataReader reader) 
{ 
    return Enumerate(reader, false); 
} 

public static IEnumerable<IDataRecord> Enumerate(this IDataReader reader, bool useDbEnumerator) 
{ 
    if (useDbEnumerator) 
    { 
     DbEnumerator dbEnumerator = new DbEnumerator(reader); 
     while (dbEnumerator.MoveNext()) 
     { 
      yield return (IDataRecord)dbEnumerator.Current; 
     } 
    } 
    else 
    { 
     while (reader.Read()) 
     { 
      yield return reader; 
     } 
    } 
}