使用IDataReader作为IEnumerable <T>的最佳方法?

b2L*_*ord 4 .net c# ienumerable extension-methods

我需要在任何像这样的IDataReader实现上使用Linq

var c = sqlDataReader.AsEnumerable().Count();
Run Code Online (Sandbox Code Playgroud)

例:

public abstract class Test
{
    public abstract SqlDataReader GetSqlDataReader();

    public void Foo()
    {
        SqlDataReader sqlDataReader = GetSqlDataReader();
        IEnumerable<SqlDataReader> sqlEnumerable = sqlDataReader.AsEnumerable();
        var c = sqlEnumerable.Count();
        var s = sqlEnumerable.Sum();
        SqlDataReader first = sqlEnumerable.First();
        var t = first.GetSqlXml(10);
    }
}
Run Code Online (Sandbox Code Playgroud)

写这个的最好方法是什么.请写下你的代码片段.

Ser*_*rge 15

你可以用这个:

MyDataReader.Cast<IDataRecord>()
Run Code Online (Sandbox Code Playgroud)

但是在关闭DataReader之前不要忘记执行linq语句.
例如,使用ToList()


Geo*_*ett 8

您可以创建一个扩展方法来执行此操作(请参阅下面的警告):

public static class DataReaderExtension
{
    public static IEnumerable<Object[]> AsEnumerable(this System.Data.IDataReader source)
    {
        if (source == null)
            throw new ArgumentNullException("source");

        while (source.Read())
        {
            Object[] row = new Object[source.FieldCount];
            source.GetValues(row);
            yield return row;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里找到:http://www.thinqlinq.com/default/Consuming-a ChallReader-with- LINQ.aspx


正如@LukeH指出的那样,请注意,由于IDataReader仅支持一次转发,因此您只能查询一次可枚举数.(为了解决这个问题,你可以调用ToList/ToArray,然后查询).

请注意,SqlDataReader已经暗示IEnumerable,因此您不需要在您给出的示例中执行此操作.

另外,请注意,在服务器上进行任何过滤/聚合可能更好(例如,通过LINQ to SQL)


hal*_*rty 8

试试这个:

public static class DataReaderExtension
{
    public class EnumeratorWrapper<T>
    {
        private readonly Func<bool> moveNext;
        private readonly Func<T> current;

        public EnumeratorWrapper(Func<bool> moveNext, Func<T> current)
        {
            this.moveNext = moveNext;
            this.current = current;
        }

        public EnumeratorWrapper<T> GetEnumerator()
        {
            return this;
        }

        public bool MoveNext()
        {
            return moveNext();
        }

        public T Current
        {
            get { return current(); }
        }
    }

    private static IEnumerable<T> BuildEnumerable<T>(
            Func<bool> moveNext, Func<T> current)
    {
        var po = new EnumeratorWrapper<T>(moveNext, current);
        foreach (var s in po)
            yield return s;
    }

    public static IEnumerable<T> AsEnumerable<T>(this T source) where T : IDataReader
    {
        return BuildEnumerable(source.Read, () => source);
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 6

您可以将其加载DataReader到 a 中DataTable,然后Select()

DataTable dt = new DataTable();
dt.Load(dataReader);
DataRow[] rows = dt.Select();        //DataRow[] Implements IEnumerable
Run Code Online (Sandbox Code Playgroud)

或者

IEnumerable<DataRow> rows = dt.AsEnumerable();
Run Code Online (Sandbox Code Playgroud)


Lar*_*rry 5

这是我的两分钱:

public static IEnumerable<T> Enumerate<T>(this T reader) where T: IDataReader 
{ 
   using(reader) 
      while(reader.Read()) 
         yield return reader; 
} 

public void Test()
{
  var Res =
    from Dr in MyDataReader.Enumerate()
    select new {
      ID = (Guid)Dr["ID"],
      Description = Dr["Desc"] as string
    };
}
Run Code Online (Sandbox Code Playgroud)

我强烈希望发布此内容,因为处理完DataReader售后使用非常重要,没有答案提及它。

这就是为什么我的实现usingwhile循环中有一条语句。通过这种方式,我可以进行“单手”查询,而不必担心如何DataReader处理。