Помогите с запросом

Как сконструировать условие 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

нужно его написать на шарпе..

Нравится

3 комментария

Как-то так:

...
                .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("Киев"))

  1. Получение значения из первой строки, первого столбца выборки

    Есть два способа

    var name = select.ExecuteScalar<string>();

    или

    string name;

    using (var dbExecutor = UserConnection.EnsureDBConnection()) {

            name = select.ExecuteScalar<string>(dbExecutor);

    }

    Оба способа вернут один и тот же результат. Если вы выполняете одиночный запрос тогда используйте первый вариант, он является оберткой над вторым. Второй вариант, с передачей dbExecutor-а, будет полезен если выполнять несколько запросов к БД в рамках одной транзакции.

  2. Получение списка значений:

    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));

                    }

            }

    }

  3. Выполнение запроса в рамках транзакции:

    Оба запроса в базу будут выполнены в рамках транзакции и в случае свала транзакция откатится.

    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.

Подписаться на обновления этого материала

Показать все комментарии