SqlQuery

Кастомный SqlQuery полезен в тех случаях, когда необходима предварительная обработка данных, которую проще реализовать на C#, и не нужно передавать клиенту лишние данные, используемые в обработке.

Для создания кастомных SqlQuery достаточно подключения основной библиотеки WorkflowEngine.dll.

Описание запроса

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

<SqlQuery Name="CustomSqlQuery" Type="CustomSqlQuery" Assembly="TemplateEngine">
  <Text>
    SELECT
      null AS "Field0",
      null AS "Field1",
      null AS "Field2"
    LIMIT 0;
  </Text>
  <MySqlQuery>
    <Text>
      SELECT
        city.city_id AS "CityId",
        city.title AS "Title",
        city.archive AS "Archive"
      FROM
        template.city
      ORDER BY city.title;
    </Text>
  </MySqlQuery>
</SqlQuery>

В тэге <Text> можно указать запрос, который будет описывать поля ответа, доступные на форме, и не будет содержать записей. Такая договоренность позволяет понять структуру ответа без необходимости открывать исходный код элемента.

Тэг <MySqlQuery> является вспомогательным для получения данных, которые необходимо предварительно обработать. Таких тэгов может быть несколько - все зависит от задачи.

Обращение к запросу

Обращение к кастомному SqlQuery на форме ничем не отличается от обращения к платформенным SqlQuery:

<DataConnection Name="CustomPrimaryGetDataConnection" Type="PrimaryGetDataConnection" Assembly="DataConnections">
  <SqlQuery Name="CustomSqlQuery" Type="Select">
    <Workflow Name="Template" />
    <Fields>
      <Field Name="Field0" />
      <Field Name="Field1" />
      <Field Name="Field2" />
    </Fields>
  </SqlQuery>
</DataConnection>

Так же указываем поля таблицы, которую сервер возвращает клиентской части.

Исходный код

CustomSqlQuery.cs
using System;
using System.Data;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Common;

namespace WorkflowEngine
{
    public class CustomSqlQuery : AbstractSqlQuery
    {
        private const string TEXT_ELEMENT = "Text";
        private const string MY_SQL_QUERY = "MySqlQuery";

        private string _mySqlQueryText;

        private readonly ISqlQueryHelper _sqlQueryHelper;

        public CustomSqlQuery(IServiceProvider serviceProvider) : base(serviceProvider)
        {
            // Объект для замены переменных в тексте запроса
            _sqlQueryHelper = serviceProvider.GetService<ISqlQueryHelper>();
        }

        public override void Init(System.Xml.XmlNode node)
        {
            // В методе базового класса разбирается тэг <Text>, значение которого можно получить через переменную sqlQueryText
            base.Init(node);

            // Получаем значение из тэга <Text>, вложенного в тэг <MySqlQuery>
            _mySqlQueryText = XmlParser.GetRequiredElementValue<string>(
                node, $"{MY_SQL_QUERY}/{TEXT_ELEMENT}", Name, this);
        }

        public async override Task<DataTable> Execute(IDatabaseConnection connection, Dictionary<string, object> parameters)
        {
            // Выполнение текста запроса из sqlQueryText, предварительно заменив переменный в тексте на значения параметров
            var result = await connection.ExecuteQueryAsync(GetQueryText(parameters)).ConfigureAwait(false);

            // Выполнение текста дополнительного запрос, предварительно заменив переменный в тексте на значения параметров
            var myTable = await connection.ExecuteQueryAsync(_sqlQueryHelper.GetQueryText(_mySqlQueryText, parameters));

            // Здесь будет код по обработке данных из запросов и формированию итоговой таблицы
            /*
              foreach (DataRow dataRow in myTable.Rows) {
                var newRow = result.NewRow();

                newRow["Field0"] = ...;
                newRow["Field1"] = ...;
                newRow["Field2"] = ...;

                result.Rows.Add(newRow);
            }
            */

            return result;
        }
    }
}

В конструкторе CustomSqlQuery используется метод GetService объекта типа ServiceProvider для получения объекта типа ISqlQueryHelper, который помогает построить текст запроса, заменив в нем переменные в круглых скобках {} на нужные значения:

_sqlQueryHelper = serviceProvider.GetService<ISqlQueryHelper>();

В методе Init описывается парсинг xml-кода, для получение данных из серверного xml-файла. Статический метод GetRequiredElementValue класса XmlParser используется для получения значения обязательного тэга, путь до которого указывается в параметре string path. В качестве результата метод вернет строку. Если элемент отсутствует, будет возвращено исключение типа InvalidXmlException. Если необходимо получить значение необязательного элемента, то следует использовать метод GetElementValue. Этот метод в случае отсутствия элемента будет возвращать значение по умолчанию, переданное в параметрах метода.

В методе Execute описывается логика кастомного запроса, прописываются команды на выполнение запросов к базе данных и формируется объект типа DataTable, который будет отправляться в качестве ответа на клиентскую часть.

Для выполнения SQL-запросов используется метод ExecuteQueryAsync у объекта типа IDatabaseConnection, результатом которого будет объект типа DataTable:

Last updated