web-dev-qa-db-ja.com

行ごとではなく、DataTable全体を一度にデータベースに挿入しますか?

DataTableがあり、データベーステーブルにすべてをプッシュする必要があります。

Foreachですべてを取得し、一度に各行を挿入できます。ただし、数千行あるため、これは非常に遅くなります。

データテーブル全体を一度に実行する方法はありますか?

DataTableには、SQLテーブルよりも少ない列があります。残りはNULLのままにしてください。

25
Kyle

SqlBulkCopyはこれを簡単に行う方法であり、SQL Serverでストアドプロシージャを記述する必要がないことを発見しました。

実装方法の例を次に示します。

// take note of SqlBulkCopyOptions.KeepIdentity , you may or may not want to use this for your situation.  

using (var bulkCopy = new SqlBulkCopy(_connection.ConnectionString, SqlBulkCopyOptions.KeepIdentity))
{
      // my DataTable column names match my SQL Column names, so I simply made this loop. However if your column names don't match, just pass in which datatable name matches the SQL column name in Column Mappings
      foreach (DataColumn col in table.Columns)
      {
          bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
      }

      bulkCopy.BulkCopyTimeout = 600;
      bulkCopy.DestinationTableName = destinationTableName;
      bulkCopy.WriteToServer(table);
}
58
Kyle

DataTableが既にあり、SQL Server 2008以降を使用していると想定しているため、これはおそらく最も簡単な方法です。まず、データベースで、次の2つのオブジェクトを作成します。

CREATE TYPE dbo.MyDataTable -- you can be more speciifc here
AS TABLE
(
  col1 INT,
  col2 DATETIME
  -- etc etc. The columns you have in your data table.
);
GO

CREATE PROCEDURE dbo.InsertMyDataTable
  @dt AS dbo.MyDataTable READONLY
AS
BEGIN
  SET NOCOUNT ON;

  INSERT dbo.RealTable(column list) SELECT column list FROM @dt;
END
GO

C#コードで:

DataTable tvp = new DataTable();
// define / populate DataTable

using (connectionObject)
{
    SqlCommand cmd = new SqlCommand("dbo.InsertMyDataTable", connectionObject);
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter tvparam = cmd.Parameters.AddWithValue("@dt", tvp);
    tvparam.SqlDbType = SqlDbType.Structured;
    cmd.ExecuteNonQuery();
}

質問でより具体的な詳細を指定していた場合、私はより具体的な回答をしたでしょう。

31
Aaron Bertrand

このアプローチ を検討してください。forループは必要ありません。

using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
    bulkCopy.DestinationTableName = 
        "dbo.BulkCopyDemoMatchingColumns";

    try
    {
        // Write from the source to the destination.
        bulkCopy.WriteToServer(ExitingSqlTableName);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
3
jaleel

私はユーザー定義のデータ型を好むでしょう:それは超高速です。

ステップ1:SQL Server DBにユーザー定義テーブルを作成する

CREATE TYPE [dbo].[udtProduct] AS TABLE(
  [ProductID] [int] NULL,
  [ProductName] [varchar](50) NULL,
  [ProductCode] [varchar](10) NULL
)
GO

手順2:ユーザー定義型でストアドプロシージャを作成する

CREATE PROCEDURE ProductBulkInsertion 
@product udtProduct readonly
AS
BEGIN
    INSERT INTO Product
    (ProductID,ProductName,ProductCode)
    SELECT ProductID,ProductName,ProductCode
    FROM @product
END

ステップ3:C#からストアドプロシージャを実行する

SqlCommand sqlcmd = new SqlCommand("ProductBulkInsertion", sqlcon);
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.Parameters.AddWithValue("@product", productTable);
sqlcmd.ExecuteNonQuery();

考えられる問題:ユーザー定義テーブルの変更

実際には、ユーザー定義タイプを変更するためのSQLサーバーコマンドはありませんが、管理スタジオでは、次の手順からこれを達成できます

タイプのスクリプトを生成します。(新しいクエリウィンドウまたはファイルとして)2.ユーザー定義テーブルを削除します。 3.作成スクリプトを変更して実行します。

1
Shamseer K

DataTable-> SQLテーブルの直線パスから少し逸脱できる場合は、オブジェクトのリストを使用して行うこともできます。

1)DataTable->オブジェクトの汎用リスト

public static DataTable ConvertTo<T>(IList<T> list)
{
    DataTable table = CreateTable<T>();
    Type entityType = typeof(T);
    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entityType);

    foreach (T item in list)
    {
        DataRow row = table.NewRow();

        foreach (PropertyDescriptor prop in properties)
        {
            row[prop.Name] = prop.GetValue(item);
        }

        table.Rows.Add(row);
    }

    return table;
}

ソースと詳細は here にあります。欠落しているプロパティーはデフォルト値のままです(intsの場合は0、参照タイプの場合はnullなど)。

2)オブジェクトをデータベースにプッシュする

1つの方法は、EntityFramework.BulkInsert拡張子。ただし、EFデータコンテキストが必要です。

高速挿入に必要なBULK INSERTコマンドを生成します(ユーザー定義のテーブルタイプソリューションはこれよりもはるかに低速です)。

まっすぐな方法ではありませんが、 がはるかにメモリ効率が高いと思われるDataTablesの代わりにオブジェクトのリストを操作するベースを構築するのに役立ちます

1
Alexei

テーブル値パラメーターを使用してこれを行うことができます。

次の記事をご覧ください。

http://www.codeproject.com/Articles/39161/C-and-Table-Value-Parameters

0
MrEyes