从SqlDataReader填充数组(或arraylist)
有没有办法通过SqlDataReader(或任何其他C#ADO.NET对象)填充数组而不循环遍历所有项目? 我有一个返回单个列的查询,我想将它放入一个字符串数组(或ArrayList,或List等)。
有可能的。 在.NET 2.0+中, SqlDataReader
inheritance自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集合(例如List
或ReadOnlyCollection
)是否更有用?
由于任何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; }