Creatio development guide
Это документация Creatio версии 7.11.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-2018.

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

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