2010-12-30 9 views
8

私はC#...を介してスプレッドシートファイルを読んでいます。スプレッドシートは1000行以上あります。私は、いくつかのデータベース側のロジックを実行し、レコードを更新するために、各行のデータをストアドプロシージャに送信する必要があります。私は時間を節約するために、1回の往復で1000行のデータをすべて送信するためにいくつかの助けが必要です。これらのすべての1000行のデータをグループ化する必要がある技術は何ですか。データのバルク行をストアドプロシージャに渡す

+0

SQL Serverを使用していますか?もしそうなら、どのバージョンのSQL Serverを使用していますか? –

+1

1000はそれほど多くはありません - あなたは気にする必要がありますか?とにかく目立ったパフォーマンス上の問題が発生していないと、一度に1つずつ1000行が見つかるかもしれません。一度に1つずつ行うほうが簡単な場合は、最初に試してみて、何が起こるかを見てみましょう。 –

答えて

20

SQL Server 2008以降を使用していると推測すると、いくつかの選択肢があります。これらのオプションはすべて、ニューオーリンズのTech-Ed 2010およびvideo of the session is available onlineで詳細に説明されています。以下は提示されたオプションの要約です。

オプション#1 - あなただけのテーブルにデータを「ダンプ」する必要があり、あなたは多くを行う必要がない場合は、一括挿入(本当にvideoに記載されていない)

これは素晴らしい選択肢ですデータをデータベースに取り込むことを除いて、これは、SqlBulkCopyオブジェクトを使用するADO.NETでもサポートされています。

は、すべてのデータを取り、大きな文字列を構築し、文字列全体を渡す区切りのリストを渡します - 私はまた、より簡単に

オプション#2 lightweight wrapper you can find on CodePlexは、SQL ServerとADO.NETでの作業にするために書かれていますストアドプロシージャに格納します。これは驚くほど速いですが、多くの手荷物が付いてきます。データを取得し、SQL-CLRで分割するのに必要な最高のパフォーマンスを得るには、分割機能が必要です。データベースを所有していない場合は、showstopperにすることができます。

オプション#3 - あなたは再び一つのパラメータに巨大な文字列で渡しているので、これはオプション#2とほぼ同じであるXML

として渡します。これには妥当なパフォーマンスもありますが、Option#2と同じ手荷物の多くは、SQL ServerがXMLの解析方法を知っているため、分割機能はありません。

オプション#4 - このオプションは、非常にクールで、最高のパフォーマンスを提供します。表値関数(SQL Server 2008の)

を使用してください。まず、SQL Serverで "テーブル"型の値型を作成し、その値の型をパラメータとして持つストアドプロシージャを作成します。 C#では、SqlCommandを作成し、SqlDbType.Structured型のパラメータを追加できます。

cmd.CommandType = CommandType.StoredProcedure; 
cmd.CommandText = "Test.spTVP"; 
var p = cmd.Parameters.Add("@Values", SqlDbType.Structured); 
p.TypeName = "Test.OrderTableType"; 
p.Value = dataTable; 
cmd.Execute…; 

ストアドプロシージャが実行されると、すべてのデータがストアドプロシージャのテーブル変数で使用できます。他のテーブル変数と同様に使用することができ、データの移動は非常に簡単です。

オプション#5からストリーミング表値関数(SQL Server 2008の)

を使用してもう少し作業後、オプション#4あなたはセットアップにイテレータを持っていますが、外にいくつかのクレイジーなパフォーマンスを得るため、ストアドプロシージャに渡す前にすべてのデータをクライアントにロードする必要がないためです。 .NETランタイムは実際にデータをデータベースにストリーミングし、ストアドプロシージャの実装は同じです。

class MyStreamingTvp : IEnumerable<SqlDataRecord> { … 
} 
… 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.CommandText = "Test.spTVP"; 
var p = cmd.Parameters.Add("@Values", SqlDbType.Structured); 
p.TypeName = "Test.OrderTableType"; 
p.Value = new MyStreamingTvp(…); 
cmd.Execute…; 

これらのオプションはすべて、非常に詳細と私は冒頭で述べたvideoで少しユーモアで覆われています。今年Tech-Edで私が気に入ったセッションのひとつでした。

+0

+1:非常に良いオプション、私はもっと投票できることを願っています – TalentTuner

+0

@Saurabh私はあなたのためにそれをしました:-) –

+0

こんにちはライアン、非常に良い答え!ちょうどビデオのリンクがもう働いていません。あなたは新しいリンクを投稿してもらえますか、それともあなたはまだセッションのタイトルを知っていますか?セッションのビデオはまだcannel9にあるはずです... – Markus

3

ライアンの答えは非常に徹底的で、さまざまなオプションをカバーしています。比較的少数の行(1000-5000はかなり小さいとみなされます)では、ストアドプロシージャのパラメータとしてXMLを渡して、オプション#3として概説されているものを使用します。

私はあなたのスプレッドシートのデータがシンプルで、あなたが作成したリストのようなものとしてあなたのコード内にすぐに用意されていると仮定しています。 DataTable。この簡単な例では、データを簡単にするためにDataTableと仮定します。

私は、ライアンのように、また、SQL 2008

1を想定しています - ストアドプロシージャに渡されるXMLにデータを変換することにより、C#でデータを準備します。これは単なるXML文字列です。私たちは基本データクラスのメソッドを使います。 DataTableを渡すと、ストアドプロシージャのパラメータとして渡すことができる単純なXML文字列に変換されます。

public string ConvertToXMLDataString(DataTable table) { 
     StringBuilder XMLString = new StringBuilder(); 
     if (string.IsNullOrEmpty(table.TableName)) 
      table.TableName = "DataTable"; 
     XMLString.AppendFormat("<{0}>", table.TableName); 
     DataColumnCollection tableColumns = table.Columns; 
     foreach (DataRow row in table.Rows) { 
      XMLString.AppendFormat("<RowData>"); 
      foreach (DataColumn column in tableColumns) { 
       XMLString.AppendFormat("<{1}>{0}</{1}>", row[column].ToString(), column.ColumnName); 
      } 
      XMLString.AppendFormat("</RowData>"); 
     } 
     XMLString.AppendFormat("</{0}>", table.TableName); 
     return XMLString.ToString(); 
    } 

2 - 私はConvertToXMLDataStringへのDataTableを渡すの最終結果は、きれいにフォーマットされたデータの1000行、すべての整数、10列

DataTable table = new DataTable("DataTable"); 
      for(int i = 1; i < 11; i++){ 
       table.Columns.Add(new DataColumn("Column" + i.ToString())); 
      } 
      int j = 0; 
      for (int i = 0; i < 1000; i++) { 
       DataRow newRow = table.NewRow(); 
       for (int k = 0; k < table.Columns.Count; k++) { 
        newRow[k] = j++; 
       }    
       table.Rows.Add(newRow); 
      } 

が含まれています簡単な例のデータテーブルを作成しました次に、そのXを処理するストアドプロシージャを作成 -

<DataTable> 
    <RowData> 
     <Column1>0</Column1> 
     <Column2>1</Column2> 
     <Column3>2</Column3> 
     <Column4>3</Column4> 
     <Column5>4</Column5> 
     <Column6>5</Column6> 
     <Column7>6</Column7> 
     <Column8>7</Column8> 
     <Column9>8</Column9> 
     <Column10>9</Column10> 
    </RowData> 
    <RowData> 
     <Column1>10</Column1> 
     <Column2>11</Column2> 
     <Column3>12</Column3> 
     <Column4>13</Column4> 
     <Column5>14</Column5> 
     <Column6>15</Column6> 
     <Column7>16</Column7> 
     <Column8>17</Column8> 
     <Column9>18</Column9> 
     <Column10>19</Column10> 
    </RowData> 
</DataTable> 

3:ストアドプロシージャに渡され、容易に選択することができるデータテーブルのXML表現MLデータ文字列を渡します。

CREATE PROCEDURE [dbo].[pr_Test_ConvertTable] 
@TableData XML 
AS 
BEGIN 
    SET NOCOUNT ON 
    SET ANSI_NULLS ON 
    SET ARITHABORT ON 

    DECLARE @TempTable TABLE (
     Column1 int, Column2 int, Column3 int, Column4 int, Column5 int, 
     Column6 int, Column7 int, Column8 int, Column9 int, Column10 int 
    ) 

    INSERT INTO @TempTable (Column1, Column2, Column3, Column4, Column5, Column6, Column7, Column8, Column9, Column10) 
    SELECT XmlTable.Data.value('(./Column1)[1]','int'), XmlTable.Data.value('(./Column2)[1]','int'), 
    XmlTable.Data.value('(./Column3)[1]','int'), XmlTable.Data.value('(./Column4)[1]','int'), 
    XmlTable.Data.value('(./Column5)[1]','int'), XmlTable.Data.value('(./Column6)[1]','int'), 
    XmlTable.Data.value('(./Column7)[1]','int'), XmlTable.Data.value('(./Column8)[1]','int'), 
    XmlTable.Data.value('(./Column9)[1]','int'), XmlTable.Data.value('(./Column10)[1]','int') 
    FROM @TableData.nodes('//DataTable/RowData') AS XmlTable(Data) 

    SELECT * FROM @TempTable 
END 
GO 

4 - 手順は@TableDataのXML変数を受け入れ、@TempTable呼ばれる新しく作成されたテーブル変数に挿入します。

最後に、適切なXMLパラメータを使用してデータベース呼び出しを作成します。通常と同じようにSPを呼び出し、パラメータとして使用してください。

cmd.Parameters.Add("@TableData", SqlDbType.Xml).Value = ConvertToXMLDataString(table); 

ありがとうございます。それに応じて調整してデータを扱うことができるはずです。私は、通常、DataTableを渡すことが嫌い、ObjectやListを渡すことはあまりありませんが、この状況では、おそらくDataTableにデータがあります。

これが一度しか実行されていない、またはしばしばタイプのものではない場合、XMLを使用する便宜のために取ったパフォーマンスヒットは最小限です。これが多くのユーザーによって頻繁に行われる場合は、より効率的な方法を使用してください。

+0

ああ、私は決して本当にセレクト*をしません。例のためだけに。これにしないでください。 –

関連する問題