2012-04-25 7 views
1

У меня есть процесс powershell, который работает по требованию, который собирает все журналы журнала запросов из приложения через вызовы веб-службы. Запросы результатов передаются объектам и имеют значения NoteProperty (пара значений атрибутов) в большом массиве списков (обычно 1400 элементов) в неделю.Правильное использование таблиц данных

Что я хотел сделать, так это хранить все эти запросы в исторических целях, чтобы приложение не чистило их самостоятельно. Поэтому я создал простую таблицу в базе данных, которая хранит все пары значений атрибутов для каждого запроса, который еще не существует в моей недавно созданной базе данных.

Затем я устанавливаю соединение OleDB в сценарии powershell на сервер MSSQL и выбираю все записи из таблицы, чтобы заполнить DataTable (я не очень хорошо разбираюсь в OleDB или DataTables). После того, как я прокручиваю каждый элемент в массиве списка, чтобы его проверить, он еще не существует в DataTable. Для каждой записи, которая не существует, я добавляю новую строку в DataTable с парами атрибутов-значений. Оттуда я предполагаю, что построитель команд помогает с инструкцией Insert, поэтому мне не нужно проверять каждое значение атрибута, если оно пустое или пустое или даже вообще пишет запрос. Затем, наконец, я обновляю OleDBAdapter с помощью недавно добавленного DataTable.

Хотя этот процесс работает, я понял, что то, что он делает, это сбрасывать все данные из базы данных, а затем сравнивать с моим массивом списков и переписывать вновь добавленные записи. Чем больше база данных, тем дольше это занимает. Есть ли способ быстро и эффективно сделать это без необходимости писать какие-либо операторы 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, я буду смотреть в использовании таблицы Ценится параметров, хотя я не уверен, если у меня есть доступ к созданию процедур магазин –

Смежные вопросы