DataTableがあり、データベーステーブルにすべてをプッシュする必要があります。
Foreachですべてを取得し、一度に各行を挿入できます。ただし、数千行あるため、これは非常に遅くなります。
データテーブル全体を一度に実行する方法はありますか?
DataTableには、SQLテーブルよりも少ない列があります。残りはNULLのままにしてください。
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);
}
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();
}
質問でより具体的な詳細を指定していた場合、私はより具体的な回答をしたでしょう。
このアプローチ を検討してください。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);
}
}
私はユーザー定義のデータ型を好むでしょう:それは超高速です。
ステップ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.作成スクリプトを変更して実行します。
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 にあります。欠落しているプロパティーはデフォルト値のままです(int
sの場合は0、参照タイプの場合はnullなど)。
2)オブジェクトをデータベースにプッシュする
1つの方法は、EntityFramework.BulkInsert
拡張子。ただし、EFデータコンテキストが必要です。
高速挿入に必要なBULK INSERTコマンドを生成します(ユーザー定義のテーブルタイプソリューションはこれよりもはるかに低速です)。
まっすぐな方法ではありませんが、 がはるかにメモリ効率が高いと思われるDataTable
sの代わりにオブジェクトのリストを操作するベースを構築するのに役立ちます 。
テーブル値パラメーターを使用してこれを行うことができます。
次の記事をご覧ください。
http://www.codeproject.com/Articles/39161/C-and-Table-Value-Parameters