Powershell - 无效尝试调用FieldCount - Reader已关闭?

时间:2016-02-19 15:36:08

标签: sql-server powershell

我有一个PowerShell脚本,用于循环SQL Server列表并从这些服务器中提取扩展事件数据。它在95%的SQL Server上工作得很好但是我的SQL Server大约有5%我得到了这个错误:

  

写数据表:System.Management.Automation.MethodInvocationException:   使用“1”参数调用“WriteToServer”的异常:

     

“读取器关闭时无法尝试调用FieldCount。”   System.InvalidOperationException:无效尝试调用FieldCount   当读者关闭时。

     

at System.Data.SqlClient.SqlDataReader.get_FieldCount()at   System.Data.SqlClient.SqlBulkCopy.WriteToServer(IDataReader reader)at   CallSite.Target(Closure,CallSite,Object,Object)   ---内部异常堆栈跟踪结束---在System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext)   funcContext,异常异常)at   System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame   框架)   System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame   框架)   System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame   帧).Message

我不明白为什么我的脚本可以在大多数SQL Server上运行,但不是全部。

我的PowerShell脚本:

#Create your SQL connection string to your central collection database  
$ServerAConnectionString = "Data Source=SourceServer;Initial Catalog=SourceDatabase;Integrated Security=True;" $ServerAConnection = new-object system.data.SqlClient.SqlConnection($ServerAConnectionString);

#Create a Dataset to hold the DataTable from DBServers 
$dataSet = new-object "System.Data.DataSet" "DBServers" $query = "SET NOCOUNT ON;" $query = $query + " SELECT ServerName, FilePath " $query = $query
        + " FROM dbo.SourceTable " $query = $query + " WHERE Domain = 'domain'  " $query = $query + " AND XEventQueryEnabled = 1 "
        #write-host $query;

#Create a DataAdapter which youll use to populate the DataSet with the instances to collect from 
$dataAdapter = new-object "System.Data.SqlClient.SqlDataAdapter" ($query, $ServerAConnection) $dataAdapter.Fill($dataSet) #| Out-Null   $ServerAConnection.Open() $sourceConnection  = New-Object System.Data.SqlClient.SQLConnection($SourceConnectionString)


$CollectionTime = date;    foreach($a in $dataSet.Tables[0].Rows) {   write-host "DBServer: " $a.ServerName;       # set connection string for the remote server
    $SourceConnectionString = "Server="+$a.Servername+"; Initial Catalog = master; integrated security = true"    # set connection string for the central collection server
    $DestinationConnectionString = "Data Source=RepositoryServer;Initial Catalog=RepositoryDatabase;Integrated Security=True"
     try
    {
    $sql =  "        WITH cte (event_data) as "
    $sql =  $sql + " (SELECT CAST(event_data AS XML) AS event_data "
    $sql =  $sql + " FROM sys.fn_xe_file_target_read_file(N'"+$a.FilePath+"MyXevents*.xel', NULL, NULL, NULL)) "
    $sql =  $sql + " SELECT @@SERVERNAME, * FROM cte "
    $sql =  $sql + " WHERE  SWITCHOFFSET(event_data.value('(event/@timestamp)[1]', 'datetimeoffset'),DATEPART(Tzoffset, SYSDATETIMEOFFSET())) > '2/1/16' "
       try{
            write-host "Collecting XEvent XML Data from Remote SQL Server.";
            $tableName = "RepositoryTable"
            $sourceConnection.ConnectionString = $SourceConnectionString
            $sourceConnection.open()
            $commandSourceData  = New-Object system.Data.SqlClient.SqlCommand($sql,$sourceConnection)

            $reader = $commandSourceData.ExecuteReader()

            $commandSourceData.CommandTimeout = '300'
        }
        Catch
        {
            $ex1 = $_.Exception.Message

        }  # end CATCH block for bad file/offset
            write-host "Inserting XEvent XML Data to Repository.";
            $bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $DestinationConnectionString
            $bulkCopy.DestinationTableName = $tableName
            $bulkCopy.BatchSize = 5000
            $bulkCopy.BulkCopyTimeout = 0
            $bulkCopy.WriteToServer($reader)

        $reader.Close()    }
    catch
    {
        $ex = $_.Exception
        Write-Host "Write-DataTable$($connectionName):$ex.Message"
    }
    finally
    {
        write-host "Finished Collecting XEvent XML Data.";
       # $reader.close()
    }
    $sourceConnection.close() }
#Close the connection as soon as you are done with it $ServerAConnection.Close()

1 个答案:

答案 0 :(得分:0)

问题是在Execute Reader之后指定了SQL Command Timeout属性。

之前:

foreach($a in $dataSet.Tables[0].Rows)
{
  write-host "DBServer: " $a.ServerName;   
   # set connection string for the remote server
    $SourceConnectionString = "Server="+$a.Servername+"; Initial Catalog = master; integrated security = true"
   # set connection string for the central collection server
    $DestinationConnectionString = "Data Source=;Initial Catalog=;Integrated Security=True"

     try
    {
    $sql =  "        WITH cte (event_data) as "
    $sql =  $sql + " (SELECT CAST(event_data AS XML) AS event_data "
    $sql =  $sql + " FROM sys.fn_xe_file_target_read_file(N'"+$a.FilePath+"*.xel', NULL, NULL, NULL)) "
    $sql =  $sql + " SELECT @@SERVERNAME, * FROM cte "
    $sql =  $sql + " WHERE  SWITCHOFFSET(event_data.value('(event/@timestamp)[1]', 'datetimeoffset'),DATEPART(Tzoffset, SYSDATETIMEOFFSET())) between '2/1/16' and '2/2/16' "

       try{
            write-host "Collecting XEvent XML Data from Remote SQL Server.";
            $tableName = "XEventXMLData"
            $sourceConnection.ConnectionString = $SourceConnectionString
            $sourceConnection.open()
            $commandSourceData  = New-Object system.Data.SqlClient.SqlCommand($sql,$sourceConnection)

            $reader = $commandSourceData.ExecuteReader()

            $commandSourceData.CommandTimeout = '300'

        }
        Catch
        {
            $ex1 = $_.Exception.Message

        }  # end CATCH block for bad file/offset
            write-host "Inserting XEvent XML Data to Repository.";
            $bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $DestinationConnectionString
            $bulkCopy.DestinationTableName = $tableName
            $bulkCopy.BatchSize = 5000
            $bulkCopy.BulkCopyTimeout = 0
            $bulkCopy.WriteToServer($reader)

        $reader.Close()
   }
    catch
    {
        $ex = $_.Exception
        Write-Host "Write-DataTable$($connectionName):$ex.Message"
    }
    finally
    {
        write-host "Finished Collecting XEvent XML Data.";
       # $reader.close()
    }
    $sourceConnection.close()

}

后:

foreach($a in $dataSet.Tables[0].Rows)
{
  write-host "DBServer: " $a.ServerName;   
   # set connection string for the remote server
    $SourceConnectionString = "Server="+$a.Servername+"; Initial Catalog = master; integrated security = true"
   # set connection string for the central collection server
    $DestinationConnectionString = "Data Source=;Initial Catalog=;Integrated Security=True"

     try
    {
    $sql =  "        WITH cte (event_data) as "
    $sql =  $sql + " (SELECT CAST(event_data AS XML) AS event_data "
    $sql =  $sql + " FROM sys.fn_xe_file_target_read_file(N'"+$a.FilePath+"*.xel', NULL, NULL, NULL)) "
    $sql =  $sql + " SELECT @@SERVERNAME, * FROM cte "
    $sql =  $sql + " WHERE  SWITCHOFFSET(event_data.value('(event/@timestamp)[1]', 'datetimeoffset'),DATEPART(Tzoffset, SYSDATETIMEOFFSET())) > '2/1/16' "

    write-host "Collecting XEvent XML Data from Remote SQL Server.";
    $sourceConnection.ConnectionString = $SourceConnectionString
    $sourceConnection.open()

    $commandSourceData = New-Object system.Data.SqlClient.SqlCommand
    $commandSourceData.CommandText = $sql
    $commandSourceData.Connection = $sourceConnection
    $commandSourceData.CommandTimeout = 0

    $reader = $commandSourceData.ExecuteReader()

    write-host "Inserting XEvent XML Data to Repository.";
    $bulkCopy = new-object ("Data.SqlClient.SqlBulkCopy") $DestinationConnectionString
    $bulkCopy.DestinationTableName = $tableName
    $bulkCopy.BatchSize = 5000
    $bulkCopy.BulkCopyTimeout = 0
    $bulkCopy.WriteToServer($reader)

    $reader.Close()
   }
    catch
    {
        $ex = $_.Exception
        Write-Host "Write-DataTable$($connectionName):$ex.Message"
    }
    finally
    {
        write-host "Finished Collecting XEvent XML Data.";
       # $reader.close()
    }
    $sourceConnection.close()

}