24

JSON と SQLBulkCopy は初めてです。C# を使用して Microsoft SQL に一括コピー/挿入する JSON 形式の POST データがあります。

JSON 形式:

{
    "URLs": [{
        "url_name": "Google",
        "url_address": "http://www.google.com/"
    },
    {
        "url_name": "Yahoo",
        "url_address": "http://www.yahoo.com/"
    },
    {
        "url_name": "FB",
        "url_address": "http://www.fb.com/"
    },
    {
        "url_name": "MegaSearches",
        "url_address": "http://www.megasearches.com/"
    }]
}

クラス:

public class UrlData
{
    public List<Url> URLs {get;set;}
}

public class Url
{
    public string url_address {get;set;}
    public string url_name {get;set;}
}

どうすればそれを効率的に行うことができますか?

4

6 に答える 6

39

TL;DRデータが既に として表されている場合はDataTable、次を使用してサーバー上の宛先テーブルに挿入できますSqlBulkCopy

string csDestination = "put here the a connection string to the database";

using (SqlConnection connection = new SqlConnection(csDestination))
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
    connection.Open()
    bulkCopy.DestinationTableName = "TUrls";
    bulkCopy.WriteToServer(dataTableOfUrls);
}

「10 から 50 の URL」だけをロードする場合は、使用する必要はありません。これSqlBulkCopyは、何千もの個別の挿入を排除するという一般的な目的です。

したがって、[および EntityFramework なしで] 挿入すること SqlBulkCopyは、1 つずつ行うことができます。

string insertQuery = "insert into TUrls(address, name) values(@address, @name)";
foreach (URL url in listOfUrls)
{
    SqlCommand cmd = new SqlCommand(insertQuery);
    cmd.Parameters.AddWithValue("@name", url.url_name);
    cmd.Parameters.AddWithValue("@address", url.urld_address);

    // Remember to take care of connection! I omit this part for clarity
    cmd.ExecuteNonQuery();
}

でデータを 挿入するSqlBulkCopyには、データ (カスタム クラス オブジェクトのリストなど) を に変換する必要がありますDataTable。以下は、そのような変換の一般的なソリューションの例として、Marc Gravell の回答からの引用です。

NuGetのFastMemberを使用した 2013 年の更新は 次のとおりです。

IEnumerable<SomeType> data = ...
DataTable table = new DataTable();
using(var reader = ObjectReader.Create(data)) {
    table.Load(reader);
}

はい、これはこれとは正反対です。リフレクションで十分です-または、より速くする必要がある場合は HyperDescriptor、2.0 またはExpression3.5 で。実際に HyperDescriptorは、十分すぎるはずです。

例えば:

// remove "this" if not on C# 3.0 / .NET 3.5
public static DataTable ToDataTable<T>(this IList<T> data)
{
    PropertyDescriptorCollection props =
        TypeDescriptor.GetProperties(typeof(T));
    DataTable table = new DataTable();
    for(int i = 0 ; i < props.Count ; i++)
    {
        PropertyDescriptor prop = props[i];
        table.Columns.Add(prop.Name, prop.PropertyType);
    }
    object[] values = new object[props.Count];
    foreach (T item in data)
    {
        for (int i = 0; i < values.Length; i++)
        {
            values[i] = props[i].GetValue(item);
        }
        table.Rows.Add(values);
    }
    return table;        
}

これで、データが として表されDataTableたので、サーバー上の宛先テーブルに書き込む準備が整いました。

string csDestination = "put here the a connection string to the database";

using (SqlConnection connection = new SqlConnection(csDestination))
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
    connection.Open()
    bulkCopy.DestinationTableName = "TUrls";
    bulkCopy.WriteToServer(dataTableOfUrls);
}

それが役に立てば幸い。

UPD

  1. @pseudonym27 の質問への回答: 「こんにちは、BulkCopy クラスを使用して SQL データベースの既存のテーブルにデータを追加できますか?」

はい、できます。BulkCopy は、データを追加する方法で挿入コマンドと同じように機能します。
また、操作がうまくいかない可能性が高く (長い挿入時間や接続の問題など)、目的のテーブルをビジー/ロックする時間をできるだけ短くしたい場合は、中間テーブルの使用を検討してください。もちろん、中間テーブルのもう 1 つの使用例は、挿入の前にいくつかのデータ変換を行う必要があることです。

于 2013-09-20T23:19:06.047 に答える
2

URL が 10 ~ 50 個しかなく、頻繁に挿入されない場合は、insert ステートメントを起動できます。シンプルで手間がかからず、dapper のように簡単かつ迅速に使用できます。

それ以外の場合は、一括コピーが必要な場合は、最初に JSON から ADO.NET データテーブルを作成して入力する必要があります。できれば、コピー先の SQL テーブルのスキーマに一致させる必要があります。それはあなたの選択です。

于 2013-09-20T21:24:51.827 に答える
2

テーブル値パラメーターを使用する必要があります。> sql server 2005を使用している場合。ここに例があります

于 2013-09-17T04:42:48.910 に答える
-1

どのデータベースを使用しているかわかりません。しかし、私はpostgresの経験があり、これは他のリレーショナルデータベースでも似ていると思います:

データベースでは、csv で区切られた値 ( Postgresなど)からもコピーできます。予想される入力形式に従って文字列をフォーマットする場合、これが最速の方法です。

于 2013-09-17T03:57:13.210 に答える