我需要在任何 IDataReader 实现上使用 Linq
var c = sqlDataReader.AsEnumerable().Count();
示例:
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);
}
}
写这个的最好方法是什么。 请写下你的片段。
答案 0 :(得分:14)
您可以使用:
MyDataReader.Cast<IDataRecord>()
但是在关闭DataReader之前不要忘记执行linq语句。
使用ToList()例如
答案 1 :(得分: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;
}
}
}
在此处找到:http://www.thinqlinq.com/default/Consuming-a-DataReader-with-LINQ.aspx
正如@LukeH指出的那样,请注意,由于IDataReader仅支持一次转发,因此您只能查询一次可枚举数。 (为了解决这个问题,你可以调用ToList / ToArray,然后查询)。
请注意SqlDataReader
已经暗示IEnumerable,因此您不需要在您给出的示例中执行此操作。
另外,请注意,在服务器上进行任何过滤/聚合可能更好(例如,通过LINQ to SQL)
答案 2 :(得分: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);
}
}
答案 3 :(得分: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
};
}
我觉得发布这个的冲动,因为在使用后处置DataReader
非常重要,没有回答提到它。
这就是我的实现在using
循环周围有while
语句的原因。通过这种方式,我可以“一手”查询,而不用担心DataReader
处置。
答案 4 :(得分:3)
您只需将DataReader
加载到DataTable
然后加载Select()
:
DataTable dt = new DataTable();
dt.Load(dataReader);
DataRow[] rows = dt.Select(); //DataRow[] Implements IEnumerable
或
IEnumerable<DataRow> rows = dt.AsEnumerable();
答案 5 :(得分:0)
我已经使用了以下内容,但我更喜欢@ Serge的建议,它让人想起我以前做过的事情,但忘记了IDataReader的实现
var reader = command.ExecuteReader();
var records = Enumerable
.Range(0, int.MaxValue)
.TakeWhile(i => reader.Read())
.Select(i => reader as IDataRecord);