Sql Bulk Copy/Insert в С#

Я новичок в JSON и SQLBulkCopy. У меня есть данные POST с форматированием JSON, которые я хочу скопировать/вставить в Microsoft SQL с помощью С#.

Формат 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;}
}

Как я могу сделать это эффективно?

Ответ 1

Поскольку вам нужно загрузить только

с 10 до 50 URL-адресов
, очевидно, нет необходимости использовать SqlBulkCopy - это для тысяч вставок. За исключением случаев, когда вам понадобится повторять эту операцию много раз.

Итак, если у вас есть список URL-адресов, т.е. список, то просто пропустите весь URL из списка и вставьте их в базу данных, например

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);

    // don't forget to take care of connection - I omit this part for clearness
    cmd.ExecuteNonQuery();
}

Но если вам действительно нужно использовать SqlBulkCopy, вам нужно преобразовать объекты класса URL в DataTable. Для этого просмотрите ответ Марка Гравелла:

Здесь хорошее обновление 2013 года с использованием FastMember от NuGet:

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

Да, это почти полная противоположность этого; рефлексии было бы достаточно - или если вам нужно быстрее, HyperDescriptor в версии 2.0 или, возможно, Expression в 3.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;        
}

Итак, вы можете использовать одно из решений Marc для создания DataTable из List<URL>. Затем вам просто нужно написать таблицу в таблицу назначения на сервере:

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

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

Надеюсь, что это поможет.

UPD

  • Ответ на вопрос @pseudonym27: "Привет, я могу использовать класс BulkCopy для добавления данных в существующую таблицу в базе данных SQL?"

Конечно, вы можете, потому что BulkCopy работает как команда вставки, но делает это немного иначе, что все. Я бы рекомендовал использовать промежуточные таблицы в случае, если операция имеет большую вероятность ошибиться (и вы хотите заняться своей целевой таблицей как можно меньше времени), или вам нужно сделать некоторые преобразования данных, но только если вы чувствуете потребность в он.

Ответ 3

Если это всего 10-50 URL-адресов, вставляемых нечасто, вы можете отключить вставки. Простые и менее хлопотные, и вы можете использовать что-то легкое и быстрое, как dapper.

Если вам нужна массовая копия, вам нужно будет создать и заполнить ADO.NET, относящуюся к данным из вашего JSON, сначала, предпочтительно, чтобы соответствовать схеме вашей таблицы sql назначения. Это ваш выбор.

Ответ 4

Я не знаю, какую базу данных вы используете. Но у меня есть опыт работы с postgres, и я полагаю, что это похоже на другие реляционные базы данных:

В базах данных вы также можете копировать значения csv с разделителями (например, Postgres). Если вы отформатируете свои строки в соответствии с расширенным форматом ввода, это должно быть самым быстрым способом.