Нарезка транзакции Entity Framework для уменьшения использования памяти - PullRequest
1 голос
/ 15 января 2020

Итак, моя проблема в том, что мне нужно запустить приложение ASP. NET, работающее в 32-битном режиме. Но мне нужно обработать кучу записей, и это вносит огромные изменения в базу данных. В случае чего-то не получается, я должен поместить весь процесс в транзакцию. Я подумал, что если я использую DBContext.SaveChanges() после каждых 10000 обработанных записей и избавляюсь от ссылок и т. Д. c. так что GC может сделать свою работу, может решить мою проблему, но это не так. Проблема в том, что каждый процесс, использующий БД (я имею в виду операции CRUD), значительно замедляется (даже в 10 раз медленнее или около того).

Поэтому мой код выглядит примерно так:

public void StartProcess()
{
    localScopeCtx = cont.Resolve<IApplicationDbContext>();
    IDbContextTransaction trans = localScopeCtx.BeginTransaction();

    int take = 10000;
    int index = 1;
    while (index <= needToProcess)
    {
        var records = GetRecords(take)
        List<obj> recordsToDelete;
        ProcessRecords(take, out recordsToDelete);

        localScopeCtx.Records.RemoveRange(recordsToDelete);

        localScopeCtx.SaveChanges();

        DetachAllEntities(localScopeCtx);
    }

    trans.Commit();
}

public void DetachAllEntities(IApplicationDbContext dbContext)
{
    var changedEntriesCopy = dbContext.ChangeTracker.Entries()
        .Where(e => e.State == EntityState.Added ||
                    e.State == EntityState.Modified ||
                    e.State == EntityState.Deleted ||
                    e.State == EntityState.Unchanged)
        .ToList();

    foreach (var entry in changedEntriesCopy)
        entry.State = EntityState.Detached;
}

В первом л oop все нормально. Это быстро и делает свою работу как шарм. Но после одного localScopeCtx.SaveChanges() все замедляется, как я сказал. Я думаю, это потому, что EF на самом деле не отправляет изменения в базу данных, а сохраняет их в памяти (в соответствии с использованием памяти), но более умным способом, которым он никогда не исчерпывает себя (возможно, использование виртуальной памяти или итак).

Любые предложения, что может быть решением?

РЕДАКТИРОВАТЬ: Добавление метода DetachAllEntities к процессу;

1 Ответ

0 голосов
/ 16 января 2020

Хорошо, поэтому я нашел решение, и если кто-то ищет что-то подобное, вот оно:

Я понял, что без создания нового DbContext он никогда не "пропустит go" ни одного из объект, который был ранее загружен. Таким образом, решение состоит в том, чтобы изменить создание транзакции и последовательность создания DbContext и создание нового контекста после каждого «среза».

Мой код выглядит примерно так:

public void StartProcess()
{
    /*This part isn't exacly the same in my program but the point is the same: create a SqlConnection*/
    string providerName = "System.Data.SqlClient";
    string serverName = ".";
    string databaseName = "SchoolDB";

    // Initialize the connection string builder for the SQL Server provider.
    SqlConnectionStringBuilder sqlBuilder =
        new SqlConnectionStringBuilder();

    // Set the properties for the data source.
    sqlBuilder.DataSource = serverName;
    sqlBuilder.InitialCatalog = databaseName;
    sqlBuilder.IntegratedSecurity = true;

    using (SqlConnection con = new SqlConnection(sqlBuilder.ToString()))
    {
    /*From this point my tested code has exactly the same construction*/
        con.Open();
        using (SqlTransaction transaction = con.BeginTransaction())
        {
            int take = 10000;
            int index = 1;
            while (index <= needToProcess)
            {
                localScopeCtx =  new ApplicationDbContext(trans, false);

                var records = GetRecords(take)
                List<obj> recordsToDelete;
                ProcessRecords(take, out recordsToDelete);

                localScopeCtx.Records.RemoveRange(recordsToDelete);

                localScopeCtx.SaveChanges();
                localScopeCtx.Dispose()
            }
            trans.Commit();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...