Как сконструировать условие OR в Select`е? Есть запрос на TSQL:
SELECT *
FROM
[dbo].[WorkUnitAction]
WHERE
[WorkUnitId] = @p1
AND [Id] > @p2
AND [CreatedOn] @p3
AND NOT [ActionResultId] IS NULL
AND ([GroupId] > @p4 OR GroupId IS NULL)
ORDER BY
[CreatedOn] DESC
нужно его написать на шарпе..
Нравится
Как-то так:
... .And().OpenBlock("GroupId").IsNotEqual(Column.Parameter(p4)) .Or("GroupId").IsNull() .CloseBlock() ...
Тут больше по теме.
"Зверев Александр" написал:
Тут больше по теме.
За пример спасибо! А ссылка не открывается, почему-то "У Вас нет доступа к этой странице"(
Алексей, цитирую ту самую страницу.
"Венжик Игорь" написал:Часто возникает ситуация когда необходимо сделать специфичечкий запрос к БД, который невозможно или сложно воспроизвести с помощью бизнес-сущностей. Например запросы к таблицам прав доступа, к системным таблицам. (Не законченная статья...)
В таких случая необходимо строить кастомные запросы:
Select select =
new Select(UserConnection)
.Column("Id")
.Column("SysSchemaId")
.Column("Name")
.Column("SysSchemaManagerName")
.Column("SysSchemaFolderId")
.Column("MetaDataModifiedOn")
.From("VwSysSchemaInSolution")
.Where("SysSolutionId").IsEqual(new QueryParameter("solutionId", userConnection.Solution.Id))
.And("SysSchemaId").In(schemas)
.And("SysSchemaStateInSolution").IsNotEqual(Column.Const((int)StoringObjectState.Deleted))
.And().OpenBlock("LockedById").IsNull()
.Or("LockedById").IsEqual(new QueryParameter("currentUserId", userConnection.CurrentUser.Id))
.CloseBlock()
as Select;
Для выполнения запросов к БД в нашей системе есть специальный объект DBExecutor. Экземпляр которого содержится в каждом UserConnection-е. То есть одному пользователю всегда доступен только один экземпляр DBExecutor-а, и пользователь не может сам создавать новые экземпляры.
Что бы получить экземпляр DBExecutor-а необходимо вызвать метод UserConnection.EnsureDBConnection().
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
}
Для вызова всегда необходимо использовать конструкцию using!Давайте раcсмотрим несколько вариантов работы
Допустим нам необходимо выполнить простой запрос:
Select select =
new Select(UserConnection)
.Column("Name")
.From("Contact")
.Where("City").IsEqual(Column.Parameter("Киев"))
Получение значения из первой строки, первого столбца выборки
Есть два способа
var name = select.ExecuteScalar<string>();
или
string name;
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
name = select.ExecuteScalar<string>(dbExecutor);
}
Оба способа вернут один и тот же результат. Если вы выполняете одиночный запрос тогда используйте первый вариант, он является оберткой над вторым. Второй вариант, с передачей dbExecutor-а, будет полезен если выполнять несколько запросов к БД в рамках одной транзакции.Получение списка значений:
List<string> names = new List<string>();
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
using (var reader = select.ExecuteReader(dbExecutor)) {
while(reader.Read()) {
int columnOrdinal = reader.GetOrdinal("Name");
names.Add(reader.GetString(columnOrdinal));
}
}
}Выполнение запроса в рамках транзакции:
Оба запроса в базу будут выполнены в рамках транзакции и в случае свала транзакция откатится.
List<string> names = new List<string>();
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
>> dbExecutor.StartTransaction();
using (var reader = select.ExecuteReader(dbExecutor)) {
while(reader.Read()) {
int columnOrdinal = reader.GetOrdinal("Name");
names.Add(reader.GetString(columnOrdinal));
}
}
insert.Execute(dbExecutor);
>> dbExecutor.CommitTransaction();
}
Транзакция начинается вызовом метода dbExecutor.StartTransaction и заканчивается вызовом CommitTransaction или RollbackTransaction. В случае когда выполнение вышло за область видимости блока using и CommitTransaction не был вызван, происходит автоматический откат транзакции. Таким образом нет необходимости оборачивать транзакцию в try/catch блок, т.к. если был свал во время выполнения транзакция автоматически откатится.Внимание! В текущей реализации даже если не передавать dbExecutor в метод Execute(), все равно запрос будет выполнен в текущей транзакции, если такая существует. Но для избежания сложностей в будущем, всегда при выполнении нескольких запросов в рамках транзакций - всегда передавайте dbExecutor в методы Execute, ExecuteReader, ExecuteScalar.