Creatio development guide
PDF
Описание платформы
Это документация Creatio версии 7.15.0. Мы рекомендуем использовать новую версию документации.

Многопоточность при работе базой данных. Использование DBExecutor

Glossary Item Box

Общие сведения

Использование нескольких потоков при работе с базой данных через UserConnection может привести к проблемам синхронизации старта и коммита транзакций.

ВАЖНО

Проблема возникает при работе с базой данных, даже если DBExecutor не используется напрямую, а используется, например, через EntitySchemaQuery.

ВАЖНО

Поскольку для работы с базой данных используются неуправляемые (unmanaged) ресурсы, то создание экземпляра DBExecutor необходимо оборачивать в оператор using. Или же явно вызывать метод Dispose() для освобождения ресурсов. Подробнее об использовании оператора using можно можно узнать в документации "C# Guide".

Пример неправильного использования

Ниже приведен фрагмент исходного кода, в котором DBExecutor используется неправильно. Нельзя выполнять вызов методов экземпляра DBExecutor в параллельных потоках.

// Создание параллельного потока.
var task = new Task(() => {
    // Использование экземпляра DBExecutor в параллельном потоке.
    using (DBExecutor dbExecutor = UserConnection.EnsureDBConnection()) {
        dbExecutor.StartTransaction();
        //...
        dbExecutor.CommitTransaction();
    }
});
// Запуск асинхронной задачи в параллельном потоке.
// Выполнение программы в основном потоке продолжается дальше.
task.Start();
//...
var select = (Select)new Select(UserConnection)
        .Column("Id")
        .From("Contact")
        .Where("Name")
        .IsEqual(Column.Parameter("Supervisor"));
// Использование экземпляра DBExecutor в основном потоке приведет к возникновению ошибки,
// т.к. экземпляр DBExecutor уже используется в параллельном потоке.
using (DBExecutor dbExecutor = UserConnection.EnsureDBConnection()) {
    using (IDataReader dataReader = select.ExecuteReader(dbExecutor)) {
        while (dataReader.Read()) {
            //...
        }
    }
}

Пример правильного использования

Ниже приведен фрагмент исходного кода, в котором DBExecutor используется корректно. Вызов методов экземпляра DBExecutor производится последовательно, в одном потоке.

// Первое использование экземпляра DBExecutor в основном потоке.
using (DBExecutor dbExecutor = UserConnection.EnsureDBConnection()) {
    dbExecutor.StartTransaction();
    //...
    dbExecutor.CommitTransaction();
}
//...
var select = (Select)new Select(UserConnection)
        .Column("Id")
        .From("Contact")
        .Where("Name")
        .IsEqual(Column.Parameter("Supervisor"));
// Повторное использование экземпляра DBExecutor в основном потоке.
using (DBExecutor dbExecutor = UserConnection.EnsureDBConnection()) {
    using (IDataReader dataReader = select.ExecuteReader(dbExecutor)) {
        while (dataReader.Read()) {
            //...
        }
    }
}

© Terrasoft 2002-2020.

Был ли данный материал полезен?

Как можно улучшить эту статью?