2012-04-25 108 views
1

我有一個按需運行的powershell進程,它通過Web服務調用從應用程序收集所有「請求歷史記錄」日誌。結果請求被轉換爲對象,並使NoteProperty值(屬性值對)每週結束於大型列表數組(通常爲1400個項目)。正確使用數據表

我想要做的就是將所有這些請求存儲爲歷史目的,以便應用程序不會自行清除它們。因此,我在一個數據庫上創建了一個簡單的表格,該表格存儲了每個請求的所有屬性值對,這些值在我新創建的數據庫中不存在。

然後,我將powershell腳本中的OleDB連接設置爲MSSQL服務器,並從表中選擇所有記錄以填充DataTable(我對OleDB或DataTables不太好)。之後,我循環訪問列表數組中的每個項目以驗證它在DataTable中不存在。對於每個不存在的記錄,我使用屬性 - 值對在DataTable中添加一個新行。從那裏我假設命令生成器幫助使用Insert語句,因此如果它爲空或空白,甚至不寫查詢,我不必檢查每個屬性值。最後,我用新添加的DataTable「更新」OleDBAdapter。

雖然這個過程起作用,但我意識到它正在從數據庫中拉出所有數據,然後與我的列表數組進行比較並重新提交新添加的記錄。數據庫越大,需要的時間越長。無論如何,無需編寫任何SQL語句就可以快速高效地執行此操作。我喜歡CommandBuilder如何爲DataTables工作。

下面是調用以更新數據庫中的所有功能的「請求記錄」對象已經進賬

function UpdateDatabase([Parameter(Mandatory=$true)] $allRequests) 
{ 
    $objOleDbConnection = New-Object "System.Data.OleDb.OleDbConnection" 
    $objOleDbCommand = New-Object "System.Data.OleDb.OleDbCommand" 
    $objOleDbAdapter = New-Object "System.Data.OleDb.OleDbDataAdapter" 
    $objDataTable = New-Object "System.Data.DataTable" 

    $objOleDbConnection.ConnectionString = "Provider=SQLNCLI10;Server=SERVER;Database=DB1;Trusted_Connection=yes;" 
    $objOleDbConnection.Open() 

    $objOleDbCommand.Connection = $objOleDbConnection 
    $objOleDbCommand.CommandText = "SELECT * FROM dbo.RequestLog" 

    ##set the Adapter object and command builder 
    $objOleDbAdapter.SelectCommand = $objOleDbCommand 
    $objOleDbCommandBuilder = New-Object "System.Data.OleDb.OleDbCommandBuilder" 
    $objOleDbCommandBuilder.DataAdapter = $objOleDbAdapter 

    ##fill the objDataTable object with the results 
    [void] $objOleDbAdapter.Fill($objDataTable) 
    [void] $objOleDbAdapter.FillSchema($objDataTable,[System.Data.SchemaType]::Source) 

    #store all the primary keys in a list for kicking out dups 
    $sql_id = @() 
    $objDataTable.Rows | foreach { $sql_id += $_.PKID} 

    ##### 

    #loop through all the requests 
    trap { 
    "Error: $($i)" 
    } 
    $i = 0 
    $total = $allRequests.count 
    foreach ($request in $allRequests) 
    {  
     $i++ 
     write-progress -activity "Filling DataTable" -status "% Complete: $($i/$total*100)" -PercentComplete ($i/$total*100) 
     #check to see if entry already exists in our table (by primary key) 
     if (!($sql_id -contains $request.PKID.Value)) 
     { 
      #shouldn't have to do this but i noticed sometimes requests are duplicate in the list? (probably restarted the script and caught some old requests 
      $sql_id += $request.PKID.Value 

      $row = $objDataTable.Rows.Add($request.PKID.Value) 
      #go through all the attributes from the request and add them to the table 
      $list = get-member -in $request | Where-Object { $_.MemberType -eq "NoteProperty" } 
      foreach ($attr in $list) 
      { 
       if ($request.($attr.name) -ne $null) 
       { 
        $row.($attr.name) = $request.($attr.name) 
       } 
      } 

     } else { 
      #PKID already in DB 
     } 

    } 
    #update the database with our new records 
    $objOleDbAdapter.Update($objDataTable) 

    ## close the connection 
    $objOleDbConnection.Close() 
} 

回答

1

你將需要寫一個小的T-SQL代碼,以使過程更加之後高效。您需要將新行發送到SQL Server,以便在SQL Server上進行處理。一種解決方案是使用表值參數,它允許您將DataTable傳遞給SQL Server。我在這裏寫博客的例子:

http://sev17.com/2012/04/appending-new-rows-only/

+0

感謝@chad,我會考慮使用表值參數,雖然我不知道我是否有權創建存儲過程 – 2012-04-30 21:05:01