Как заполнить базу данных SQL Server списком объектов вместо зацикливания - PullRequest
0 голосов
/ 10 июля 2019

У меня есть данные, поступающие из электронной таблицы Excel, я не могу изменить, как это происходит. Есть ли решение для добавления значений IList<IList<Object>> в базу данных SQL Server вместо зацикливания, когда я достигаю предела с текущими 5k строками.

Мне также сообщили, что я не должен использовать инъекции, поэтому любые альтернативы приветствуются.

public static void Load_Table()
{
    // This function on_click populates the datagrid named JumpTable
    // this.JumpTable.ItemsSource = null; // Clears the current datagrid before getting new data
    // Pulls in the 2d table from the client sheet
    IList<IList<Object>> client_sheet = Get(SetCredentials(), "$placeholder", "Client!A2:AY");
    DBFunctions db = new DBFunctions();
    db.postDBTable("DELETE FROM Client");

    foreach (var row in client_sheet)
    {
        string exe = "INSERT INTO Client ([Tracker ID],[Request ID]) VALUES('" + row[0].ToString() + "','" + row[1].ToString() + "')";
        db.postDBTable(exe);
    }
}

Функции базы данных

public SqlConnection getDBConnection()
{
    // --------------< Function: Opens the connection to our database >-------------- \\
    string connectionString = Properties.Settings.Default.connection_string; // Gets the connection source from properties
    SqlConnection dbConnection = new SqlConnection(connectionString); // Creates the connection based off our source
    if (dbConnection.State != ConnectionState.Open) dbConnection.Open(); // If it's not already open then open the connection

    return dbConnection;
}
public DataTable getDBTable(string sqlText)
{
    // --------------< Function: Gets the table from our database >-------------- \\
    SqlConnection dbConnection = getDBConnection();

    DataTable table = new DataTable();
    SqlDataAdapter adapter = new SqlDataAdapter(sqlText, dbConnection);adapter.Fill(table);

    return table;
}

public void postDBTable(string sqlText)
{
    // --------------< Function: Post data to our database >-------------- \\
    SqlConnection dbConnection = getDBConnection();

    SqlCommand cmd = new SqlCommand(sqlText, dbConnection);cmd.ExecuteNonQuery();
}

1 Ответ

1 голос
/ 10 июля 2019

В прошлом я работал со множеством массовых загрузок данных. Существует два основных способа избежать отдельных вставок в SQL Server: список значений, вставляемых за один раз или использование массовой вставки.

первый вариант использования списка значений выглядит следующим образом:

INSERT INTO Foo (Bar,Baz)
VALUES ('bar','baz'),
       ('anotherbar','anotherbaz')

В c # вы бы перебирали свой список и создавали содержимое значений, однако сделать это без уязвимости SQL-инъекций сложно.

Второй вариант - использовать массовую вставку с массовым копированием SQL и datatable. Прежде чем перейти к приведенному ниже коду, вы должны создать DataTable, который содержит все ваши данные, а затем использовать SqlBulkCopy для вставки строк с использованием функциональности Sql, оптимизированной для вставки больших объемов данных.

using (var bulk = new SqlBulkCopy(con)
{
    //bulk mapping is a SqlBulkCopyColumnMapping[] and is not necessaraly needed if the DataTable matches your destination table exactly
    foreach (var i in bulkMapping)
    {
        bulk.ColumnMappings.Add(i);
    }

    bulk.DestinationTableName = "MyTable";

    bulk.BulkCopyTimeout = 600;
    bulk.BatchSize = 5000;

    bulk.WriteToServer(someDataTable);
}

Это два метода, включенных в структуру. Есть и другие библиотеки, которые могут помочь. Dapper один, но я не уверен, как он обрабатывает вставки на задней части. Entity Framework - это еще одна структура, но она выполняет одиночные вставки, поэтому она просто перемещает проблему из вашего кода в чужой код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...