从SqlDataReader中填充一个数组(或ArrayList)

32

是否有一种方法可以通过SqlDataReader(或任何其他C# ADO.NET对象)填充数组而无需循环遍历所有项?我有一个返回单列的查询,想将其放入字符串数组(或ArrayList、List等)中。

8个回答

56

是可以的。 在.NET 2.0+中,SqlDataReader继承自DbDataReader,后者实现了非泛型的IEnumerable。这意味着您可以使用LINQ:

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

话虽如此,循环仍然存在,只是它被隐藏在 Enumerable.Select 中,而不是明确出现在你的代码中。


如何将列表的值显示到控制台? - shawn
shawn,foreach + Console.WriteLine。 - Pavel Minaev
1
你不能在一次遍历中生成两个列表,但你不应该这样做。不要使用两个字符串列表,而是使用单个列表 - 可以是匿名类实例的列表(在这种情况下,您需要使用 var 声明变量,因为没有办法描述类型),或者元组实例的列表,或者您自己的结构/类。匿名类通常最容易,例如:var list = (from IDataRecord r in dataReader select new { FieldName1 = (string)r["FieldName1"], FieldName2 = (string)r["FieldName2"] }).ToList(); - Pavel Minaev
2
dataReader.Cast<IDataRecord>().Select(r => (string)r["FieldName"]).ToList() - Pavel Minaev
1
确保引用 using System.Linq; - Kai Hartmann
显示剩余5条评论

15
不行,因为SqlDataReader是从SQL Server数据库中读取行的只向前只读流,无论是在代码中显式循环还是隐藏在框架实现中(例如DataTable的Load方法),行的流都将被循环遍历。
似乎使用通用列表然后将列表作为数组返回是一个不错的选择。例如,
List<int> list = new List<int>();

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

回应您的评论,调用ToArray()可能会增加开销,这取决于情况。您是否需要一个对象数组来处理,还是通用集合(例如 List<T>ReadOnlyCollection<T>)更有用?


你认为TaArray()方法只是多余的开销吗? - user161433

7

自 .NET 1.1 起,SqlDataReader 就有了以下方法:getvalues

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

此代码将当前读取行的值填充到data中,并将放入数组的对象数量分配给size


1
将数组大小设置为数据的大小object [] data = new object [reader.FieldCount]; - Nando

5

由于任何IDataReader实现(包括SqlDataReader)都是按顺序读取的,因此没有办法在不循环的情况下完成此操作。即使有一个框架库方法来完成这个任务,它也必须像您一样通过读取器循环。


1
原始的OP要求使用Array、ArrayList或List。你也可以返回Array。只需调用.ToArray()方法并将其分配给先前声明的数组即可。当枚举每个元素时,数组非常快。如果列表有超过1000个元素,则比List快得多。 你可以返回Array、List或Dictionary。
ids_array = (from IDataRecord r in idReader 
select (string)r["ID"]).ToArray<string>();  

此外,如果您正在使用键的查找,例如,您可能考虑创建一个HashSet对象,具有出色的查找性能,如果您只是检查一个列表是否存在于另一个列表中以确定元素的键是否存在于HashSet对象中。示例:
 HashSet<string> hs = new HashSet<string>( 
(from IDataRecord r in idReader select (string)r["ID"]).AsEnumerable<string>() );

0

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

你可以尝试使用FluentAdo:http://fluentado.codeplex.com

    public IList<UserAccount> List()
    {
        var list = new FluentCommand<UserAccount>("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;
    }

0

如果你将SqlDataAdapter读入到一个DataTable中:

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

然后,您可以使用Joel Muller在问题中提到的System.Data.DataSetExtensions中的一些工具。

它使用了一些Linq,因此您需要使用 .Net 3.5或更高版本。


-2
var array = reader.GetValue("field_name") as long[];

虽然这段代码可能解决了问题,但是包括解释它如何以及为什么解决了问题,将有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。请编辑您的答案以添加解释,并指出适用的限制和假设。 - John Conde

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接