以下是我正在使用的代码。
Dim adapGetImages As New SqlDataAdapter("select distinct FileName from Files where Filename<>'' and (RIGHT(FileName,3) = 'gif' or RIGHT(FileName,3) = 'jpg' or RIGHT(FileName,3) = 'bmp') order by FileName", connection)
Dim dtGetImages As New DataTable()
adapGetImages.Fill(dtGetImages)
ArrayList1.AddRange(dtGetImages.Rows[0][0].ToString())
最后一行是我陷入困境的地方。好像我运行它只会添加单行,如果我说dtGetImages.Rows.ToString()
那么这只会在Arraylist中添加System.DataRow而不是它的内容。
请回复无需任何循环即可解决此问题的方法。 在此先感谢。
答案 0 :(得分:0)
这样的事情应该有效:
ArrayList1.AddRange(dtGetImages.Rows.Cast(Of DataRow)().[Select](Function(r) r(0).ToString()).ToArray())
这里有一些概念在起作用。首先,您不是要将行添加到列表中,而是将每行中的第一个值添加到列表中。正如您所提到的,您可以使用for
循环从每行中获取此值并将其添加到列表中,但是这样的循环不是非常简洁或声明性的。这就是为什么我们有LINQ(语言集成查询):一个简化值集合转换的框架。
Select
方法是LINQ框架中定义的扩展方法。它将一个函数定义为一个函数,该函数定义了对给定集合中的每个项执行的转换。调用Select
的结果时,将对每个值执行给定函数,根据结果生成新集合。在这里,我们给它功能:
Function(r) r(0).ToString()
...,告诉它:
给定变量
r
,得到r
的第0个索引并在结果上调用ToString()
。
因此,如果在Select
上调用此IEnumerable<DataRow>
方法,则生成的集合将为IEnumerable<string>
。由于ArrayList.AddRange
方法需要ICollection
,因此我们必须将IEnumerable<string>
更改为实现ICollection
的内容。事实证明,数组实现ICollection
,因此我们可以使用LINQ中的ToArray()
方法将其转换为ArrayList.AddRange
将接受的值。
只有一个问题:DataTable类是在泛型是.NET框架的一部分之前编写的,因此DataRowCollection
类实现非泛型IEnumerable
接口而不是强类型IEnumerable<DataRow>
接口。 1}}。由于我们的Select
方法需要以IEnumerable<DataRow>
开头,因此我们必须采取措施将dtGetImages.Rows
转换为IEnumerable<DataRow>
。 LINQ也提供的Cast
方法将为我们完成此操作。我们告诉Cast
我们碰巧知道给定IEnumerable
(本例中为DataRowCollection
)的所有内容都是DataRow
,因此可以安全地将项目放入DataRow
,留下我们需要使用IEnumerable<DataRow>
方法的Select
。
希望这能很好地解释事情。你应该注意的一件事是,这并没有消除循环的使用。当您致电.ToArray()
时,它会从.Select
中提取项目,该项目会从.Cast
中提取项目,该项目会在dtGetImages.Rows
上进行迭代,就像您编写for
一样1}}循环来填充数组。唯一的区别是LINQ使您的代码更具声明性。说:
对于此DataTable的Rows属性中的每个DataRow,我将创建一个名为
row
的变量。然后我将在此变量的第0个元素上调用ToString
并将结果添加到ArrayList。
......说:
我在此DataTable的Rows属性中的每个DataRow上的第0个元素上调用
ToString
,并将结果添加到ArrayList。
它们的意思大致相同,但其中一个更清晰,更简洁。
答案 1 :(得分:0)
Fill方法的MSDN page有以下注释:
处理返回多个结果的批处理SQL语句时,.NET Framework数据提供程序的Fill和FillSchema实现仅检索第一个结果的架构信息。
您是否获得了第一个结果的架构信息?