Использование IDbScope для выполнения запросов к БД
Использование IDbScope для выполнения запросов к БД¶
В платформе Tessa для выполнения запросов к БД принято использовать объект DbManager (это слой взаимодействия с базой данных из ORM BLToolkit). По сравнению со стандартными SqlCommand это позволяет упростить код и привести его к виду, поддерживаемому в платформе.
Этот объект можно получить, запросив из контейнера Unity интерфейс IDbScope, а затем создав область using, внутри которой автоматически выполнится соединение с БД, которая используется платформой (в строке default в текущей версии платформы).
Поэтому расширение должно быть зарегистрировано с указанием WithUnity:
.RegisterExtension<ICardRequestExtension, MyDbRequestExtension>(x => x
.WithOrder(ExtensionStage.AfterPlatform, 1)
.WithUnity(unityContainer
.RegisterType<MyDbRequestExtension >(
new ContainerControlledLifetimeManager()))
.WhenRequestTypes(MyRequestTypes.SomeType))
В расширении пишется конструктор, который получает из Unity объект IDbScope и записывает его в поле класса:
private readonly IDbScope dbScope;
public FormBoxRequestExtension(IDbScope dbScope)
{
this.dbScope = dbScope;
}
Далее в коде метода AfterRequest используются объекты для доступа к БД:
using Tessa.Platform.Data;
...
using (this.dbScope.Create())
{
DbManager db = this.dbScope.Db;
// начинаем транзакцию, чтобы выполнить оба запроса
// ExecuteNonQuery в одной транзакции
db.BeginTransaction();
// вызов LogCommand() записывает sql-запрос со всеми параметрами
// в queries.txt в папке веб-приложения tessa,
// но только в том случае, если в NLog.config в этой же папке
// указаны уровни логирования Trace (а не Error, как по умолчанию);
// логирование запросов удобно использовать для отладки,
// но крайне не рекомендуется для production-сервера;
// если на production логирование на уровне Error,
// то вызов LogCommand не будет отнимать процессорного времени
db
.SetCommand(
"insert into Table (Column1, Column2) values (@Column1, @Column2)",
db.Parameter("@Column1", value1),
db.Parameter("@Column2", value2))
.LogCommand()
.ExecuteNonQuery();
db
.SetCommand(
"delete from Table where ID = @ID",
db.Parameter("@ID", context.Request.CardID))
.LogCommand()
.ExecuteNonQuery();
// закрываем транзакцию (для отката - db.RollbackTransaction())
db.CommitTransaction();
// выполняем чтение данных
db
.SetCommand(
"select Column1, Column2 from Table with(nolock) where ID = @ID",
db.Parameter("@ID", context.Request.CardID))
.LogCommand();
using(var reader = db.ExecuteReader())
{
while (reader.Read())
{
var value1 = reader.GetValue<Guid?>(0);
var value2 = reader.GetValue<string>(1);
// ... обрабатываем прочитанные значения
}
}
}
Объект также можно использовать для доступа к базам данных, которые указаны в других строках подключения в файле app-db.json
веб-приложения tessa, например:
using (this.dbScope.CreateNew("1C"))
{
DbManager db = this.dbScope.Db;
// здесь через объект db мы обращаемся к базе данных,
// указанной по имени "1C" в app-db.json веб-приложения tessa
}