【问题标题】:Iterating over multiple rows of data in PowerShell在 PowerShell 中迭代多行数据
【发布时间】:2014-09-24 01:24:47
【问题描述】:

我正在编写一些 PowerShell 代码来连接数据库,读取多行数据,然后通过 SqlDataReader 将它们返回。

我是通过“C# 方式”实现的,我将如何用 C# 编写它:

function ExecuteQuery($sql) {
    $connection = new-object system.data.SqlClient.SQLConnection($ConnectionString);
    $connection.Open();

    $cmd = $connection.CreateCommand();
    $cmd.CommandText = $sql;
    $cmd.Connection = $connection    
    $reader = [System.Data.SqlClient.SqlDataReader]$cmd.ExecuteReader()
    return $reader;
}

(此函数的调用者必须负责任地自行关闭连接。)

我预计,即使没有类型转换,我也会得到System.Data.SqlClient.SqlDataReader 的实例。这一点很重要,因为我想用Read逐行迭代,更不用说我想用方括号按列名访问数据(按ID访问太脆弱了)。

不幸的是,我得到了一个System.Data.Common.DataRecordInternal 的实例,它包含Read 方法,也不允许我通过数组索引访问记录。

我的问题是:如何在 PowerShell 中读取和遍历多行数据?

【问题讨论】:

    标签: c# powershell powershell-3.0 sqlclient


    【解决方案1】:

    有几种方法可以遍历数组的成员(在您的情况下为“数据行”)。首先想到的是:

    ForEach($Record in (ExecuteQuery $CommandString){
        Do Stuff to $Record
    }
    

    或者您可以将其通过管道传输到 ForEach 循环(您可以通过这种方式将输出传输到 Out-File,如果需要):

    ExecuteQuery $CommandString | ForEach{Do stuff to $_}
    

    或者,如果您真的想要更精细的控制,我想您可以使用 For 循环并执行以下操作:

    $Results = ExecuteQuery $CommandString 
    For($i=0;$i -le $Results.count;$i++){
        Do stuff to $Results[$i]
    }
    

    【讨论】:

    • +1 效果很好,谢谢。就像 C# 一样,我可以使用 $record[0]$record['FirstName']
    【解决方案2】:

    问题是当函数返回时,PowerShell 会尝试为您枚举阅读器。您可以通过将其放入数组中来告诉 PowerShell 不理会它:

    return ,$reader
    

    【讨论】:

    • 也许我没有解释清楚我的问题?我要返回$reader。在 C# 中,与我在这里的等效代码返回一个 SqlDataReader 的实例,它可以被枚举并具有一个 Read 函数。
    • 我知道。这是 PowerShell 的怪癖之一,让我来自 .NET。 PowerShell 不会服从您并按照您的指示返回 $reader;相反,它会尝试为您枚举阅读器,而是返回 Object[]。检查您的 ExecuteReader 函数的返回类型,就像它在原始问题中一样。 ExecuteQuery($sql).GetType().FullName 将返回 Object[]。但是如果你强制将$reader 放入一个数组中,PowerShell 将不理会它,返回类型将是System.Data.SqlClient.SqlDataReader,正如预期的那样。疯狂的?我想是的,但那是 PowerShell!
    • 使用 PowerShell 3,您的 函数 返回类型为 System.Object[]。我不是指$reader inside 函数的类型。我的意思是函数实际返回的内容。我知道这是违反直觉的,但是运行ExecuteQuery($YourSqlHere).GetType().FullName 你就会明白我的意思了。 PowerShell 会在返回时尝试枚举读取器,这就是为什么预先进行转换没有帮助的原因。要停止,您必须将阅读器放入一个数组中:return ,$reader。这会将函数的返回值更改为数组,而不是数组(正如我们所期望的来自 C#),而是更改为 SqlDataReader
    • 我明白你在说什么。不幸的是,就像我的第一条评论指出的那样,返回一个数组并没有将类型从DataRecordInternal 更改为SqlDataReader。它仍在评估中。我使用接受的答案进行迭代。
    • 嗯,最重要的是它正在工作!尽管如此,我极客的一面很好奇为什么它在我们的贝壳上有所不同。您是否像我的回答一样将$reader 设为数组的第二项? return ,$reader?返回 @($reader) 并不能解决问题,但将其作为第二项使我的返回类型为 SqlDataReader
    猜你喜欢
    • 2021-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多