Самый быстрый способ вставки в Entity Framework - PullRequest
614 голосов
/ 09 мая 2011

Я ищу самый быстрый способ вставки в Entity Framework.

Я спрашиваю об этом из-за сценария, когда у вас есть активный TransactionScope, и вставка огромна (4000+).Потенциально он может длиться более 10 минут (время ожидания транзакций по умолчанию), что приведет к незавершенной транзакции.

Ответы [ 28 ]

1 голос
/ 28 мая 2013

Вы когда-нибудь пытались вставить через фоновый рабочий или задачу?

В моем случае я вставляю 7760 регистров, распределенных в 182 различных таблицах с отношениями внешних ключей (по NavigationProperties).

Без задания заняло 2 с половиной минуты.Внутри Задачи (Task.Factory.StartNew(...)) это заняло 15 секунд.

Я делаю SaveChanges() только после добавления всех сущностей в контекст.(для обеспечения целостности данных)

1 голос
/ 09 мая 2011

Насколько мне известно, no BulkInsert в EntityFramework позволяет увеличить производительность огромных вставок.

В этом сценарии вы можете перейти с SqlBulkCopy в ADO.net дорешить вашу проблему

1 голос
/ 01 октября 2015

Все решения, написанные здесь, не помогают, потому что когда вы делаете SaveChanges (), операторы вставки отправляются в базу данных один за другим, именно так работает Entity.

И если ваша поездка в базу данных и обратно составляет, например, 50 мс, то время, необходимое для вставки, равно количеству записей x 50 мс.

Вы должны использовать BulkInsert, вот ссылка: https://efbulkinsert.codeplex.com/

Я использовал время вставки с 5-6 минут до 10-12 секунд, используя его.

1 голос
/ 24 января 2019

SqlBulkCopy очень быстрый

Это моя реализация:

// at some point in my calling code, I will call:
var myDataTable = CreateMyDataTable();
myDataTable.Rows.Add(Guid.NewGuid,tableHeaderId,theName,theValue); // e.g. - need this call for each row to insert

var efConnectionString = ConfigurationManager.ConnectionStrings["MyWebConfigEfConnection"].ConnectionString;
var efConnectionStringBuilder = new EntityConnectionStringBuilder(efConnectionString);
var connectionString = efConnectionStringBuilder.ProviderConnectionString;
BulkInsert(connectionString, myDataTable);

private DataTable CreateMyDataTable()
{
    var myDataTable = new DataTable { TableName = "MyTable"};
// this table has an identity column - don't need to specify that
    myDataTable.Columns.Add("MyTableRecordGuid", typeof(Guid));
    myDataTable.Columns.Add("MyTableHeaderId", typeof(int));
    myDataTable.Columns.Add("ColumnName", typeof(string));
    myDataTable.Columns.Add("ColumnValue", typeof(string));
    return myDataTable;
}

private void BulkInsert(string connectionString, DataTable dataTable)
{
    using (var connection = new SqlConnection(connectionString))
    {
        connection.Open();
        SqlTransaction transaction = null;
        try
        {
            transaction = connection.BeginTransaction();

            using (var sqlBulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, transaction))
            {
                sqlBulkCopy.DestinationTableName = dataTable.TableName;
                foreach (DataColumn column in dataTable.Columns) {
                    sqlBulkCopy.ColumnMappings.Add(column.ColumnName, column.ColumnName);
                }

                sqlBulkCopy.WriteToServer(dataTable);
            }
            transaction.Commit();
        }
        catch (Exception)
        {
            transaction?.Rollback();
            throw;
        }
    }
}
0 голосов
/ 11 марта 2019

enter image description here

Используйте эту технику для увеличения скорости вставки записей в Entity Framework.Здесь я использую простую хранимую процедуру для вставки записей.И для выполнения этой хранимой процедуры я использую .FromSql () метод Entity Framework , который выполняет Raw SQL.

Код хранимой процедуры:

CREATE PROCEDURE TestProc
@FirstParam VARCHAR(50),
@SecondParam VARCHAR(50)

AS
  Insert into SomeTable(Name, Address) values(@FirstParam, @SecondParam) 
GO

Далее, циклчерез все ваши 4000 записей и добавьте код Entity Framework, который выполняет хранимую

процедуру каждый сотый цикл.

Для этого я создаю строковый запрос для выполнения этой процедуры, продолжая добавлять к нему каждый набор записей.

Затем проверьте, что цикл работает с кратными 100, и в этом случае выполните его, используя .FromSql().

Таким образом, для 4000 записей мне нужно выполнить процедуру только для 4000/100 = 40 раз .

Проверьте код ниже:

string execQuery = "";
var context = new MyContext();
for (int i = 0; i < 4000; i++)
{
    execQuery += "EXEC TestProc @FirstParam = 'First'" + i + "'', @SecondParam = 'Second'" + i + "''";

    if (i % 100 == 0)
    {
        context.Student.FromSql(execQuery);
        execQuery = "";
    }
}
0 голосов
/ 09 мая 2011

Секрет заключается в том, чтобы вставить в идентичный пустой промежуточный стол.Вставки быстро загораются.Затем запустите вставку single из этой таблицы в основной большой стол.Затем обрежьте промежуточный стол, готовый к следующей партии.

т.е..

insert into some_staging_table using Entity Framework.

-- Single insert into main table (this could be a tiny stored proc call)
insert into some_main_already_large_table (columns...)
   select (columns...) from some_staging_table
truncate table some_staging_table
0 голосов
/ 20 ноября 2017

Но для более (+4000) вставок я рекомендую использовать хранимую процедуру.приложил время, прошедшее.Я вставил 11.788 строк в 20 "enter image description here

вот и код

 public void InsertDataBase(MyEntity entity)
    {
        repository.Database.ExecuteSqlCommand("sp_mystored " +
                "@param1, @param2"
                 new SqlParameter("@param1", entity.property1),
                 new SqlParameter("@param2", entity.property2));
    }
0 голосов
/ 07 января 2018

Используйте хранимую процедуру, которая принимает входные данные в форме XML для вставки данных.

Из вашего кода на c # вставьте данные в формате xml.

например, в C #, синтаксис будет выглядеть так:

object id_application = db.ExecuteScalar("procSaveApplication", xml)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...