从SqlDataReader填充数组(或arraylist)

有没有办法通过SqlDataReader(或任何其他C#ADO.NET对象)填充数组而不循环遍历所有项目? 我有一个返回单个列的查询,我想将它放入一个字符串数组(或ArrayList,或List等)。

有可能的。 在.NET 2.0+中, SqlDataReaderinheritance自DbDataReader ,它实现了IEnumerable (非generics的)。 这意味着您可以使用LINQ:

 List list = (from IDataRecord r in dataReader select (string)r["FieldName"] ).ToList(); 

也就是说,循环仍然存在,它只是隐藏在Enumerable.Select ,而不是在代码中显式。

不,因为SqlDataReader是来自SQL Server数据库的仅向前只读的行流,所以行的流将通过代码中的显式循环或隐藏在框架实现(例如DataTable的Load方法)中循环。

这听起来像使用通用列表,然后将列表作为数组返回将是一个不错的选择。 例如,

 List list = new List(); using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { list.Add(reader.GetInt32(0)); } } return list.ToArray(); 

为了回应你的评论,调用ToArray()可能是开销,这取决于。 您是否需要使用一组对象,或者generics集合(例如ListReadOnlyCollection )是否更有用?

由于任何IDataReader实现(包括SqlDataReader )都将是一个只有前向的读者,所以没有循环就没有办法做到这一点。 即使有一个框架库方法来执行此操作,它也必须循环读取器,就像您一样。

显然,自.NET 1.1 SqlDataReader以来,有以下方法 :

 int size; object[] data = new object[]{}; size = reader.GetValues(data); 

这将使用当前读取器行的值填充data ,并将放入arrays的对象数量指定为大小。

如果您将SqlDataAdapter读入DataTable:

 DataTable dt as DataTable; dt.fill(data); 

然后你可以使用System.Data.DataSetExtensions一些玩具,如Joel Muller对这个问题的回答所引用的那样。

在使用一点Linq,所以你将净.Net 3.5或更高。

orignial OP要求Array,ArrayList或List。 您也可以返回Array。 只需调用.ToArray()方法并将其分配给先前声明的数组。 在枚举每个元素时,数组非常快。 如果列表包含超过1000个元素,则比List快得多。 您可以返回Array,List或Dictionary。

 ids_array = (from IDataRecord r in idReader select (string)r["ID"]).ToArray(); 

此外,例如,如果您正在使用键的查找,则可以考虑创建一个具有出色查找性能的HashSet对象,如果您只是检查一个列表而不是另一个列表以确定HashSet对象中是否存在元素键。 例:

  HashSet hs = new HashSet( (from IDataRecord r in idReader select (string)r["ID"]).AsEnumerable() ); 

你必须循环,但有些项目可以使它更简单。 另外,尽量不要使用ArrayList,而是使用List。

您可以通过以下方式查看FluentAdo: http ://fluentado.codeplex.com

  public IList List() { var list = new FluentCommand("SELECT ID, UserName, Password FROM UserAccount") .SetMap(reader => new UserAccount { ID = reader.GetInt("ID"), Password = reader.GetString("Password"), UserName = reader.GetString("UserName"), }) .AsList(); return list; }