Возможности, способы, методы работы с запросами, операциями и событиями

Сервис данных, работающий с реляционными хранилищами.

Является абстрактным классом, от него наследуется

Основные возможности SQLDataService

Поскольку SQLDataService реализует интерфейс ICSSoft.STORMNET.Business.IDataService, то он поддерживает все методы, определенные в данном интерфейсе. Следует отметить, что часть методов лишь декларируется в классе SQLDataService, а их реализация должна быть выполнена в классах-наследниках.

Дополнительные способы загрузки данных

LoadRawValues

Назначение: Загрузка без создания объектов при необходимости получить DISTINCT данные. Стандартные методы зачитки получают PrimaryKey для возможности правильного создания объектов данных. Соответственно, DISTINCT с PrimaryKey в запросе не даёт эффекта (ключи уникальные, поэтому никакой группировки результатов не произойдёт - они все разные). Данный метод возвращает обычный двумерный массив (как это делает ADO.NET).

Параметры:

customizationStruct - Структура LoadingCustomizationStruct, определяющая, что и как грузить. Должен быть указан параметр Distinct.

Сигнатура:

    virtual public object[][] LoadRawValues(LoadingCustomizationStruct customizationStruct) 

Пример:

SQLDataService ds = (SQLDataService)DataServiceProvider.DataService;
View v = new View();
v.DefineClassType = typeof (Door);
v.AddProperty("Street.Name");
LoadingCustomizationStruct lcs = LoadingCustomizationStruct.GetSimpleStruct(typeof(Door), v);
lcs.Distinct = false; //Получим двумерный массив свойств без DISTINCT в верхнем SELECT-е
object[][] loadDistinctValues = ds.LoadRawValues(lcs);
string s = loadDistinctValues.Length.ToString();

lcs.Distinct = true; //Получим двумерный массив свойств с DISTINCT в верхнем SELECT-е
object[][] loadDistinctValues1 = ds.LoadRawValues(lcs);
string s1 = loadDistinctValues1.Length.ToString();

SecondLoadObject

Назначение: Метод для дочитки объекта данных. Загруженные ранее свойства не затираются, изменённые свойства не затираются. Подменяются поштучно свойства копии данных. Перед использованием рекомендуется ознакомиться с описанием в статье Дочитка объекта данных.

Параметры:

  • dataObjectView - представление
  • dataObject - бъект данных, который требуется загрузить
  • checkExistingObject - проверять ли существование объекта в хранилище
  • dataObjectCache - кэш

Сигнатура:

protected virtual void SecondLoadObject(View dataObjectView, DataObject dataObject, bool checkExistingObject, DataObjectCache dataObjectCache) 

Дополнительные способы обновления данных

UpdateObjectsOrdered

Назначение: Обновить объекты данных в указанном порядке.

SQLDataService умеет сам выстраивать порядок запросов на обновление объектов данных. Особенно это актуально, когда есть большое количество разнотипных объектов в одной транзакции. К сожалению, не всегда есть возможность автоматизированно вычислить правильный порядок запросов. В первую очередь, это относится к ситуациям, когда в графе типов есть циклы. Для решения этой проблемы предлагается использовать данный метод, который выполняет обновление объектов последовательно в том порядке, в котором они приходят в этот метод.

Параметры:

  • objects - обновляемые объекты
  • alwaysThrowException - Если произошла ошибка в базе данных, не пытаться выполнять других запросов, сразу взводить ошибку и откатывать транзакцию.

Сигнатура:

virtual public void UpdateObjectsOrdered(ref DataObject[] objects, bool alwaysThrowException = true)

Пример:

protected void UpdateButtonClick(object sender, EventArgs e)
{
    SQLDataService ds = (SQLDataService)DataServiceProvider.DataService;
    var ko = ds.Query<КритерийОценки>(КритерийОценки.Views.КритерийОценкиE).First(o => o.Описание.StartsWith("kirlim"));
    ko.Описание = "kirlim-birlim";
DataObject[] dObjs = new DataObject[] { ko };
    ds.UpdateObjectsOrdered(ref dObjs);
}

Выполнение операций в рамках указанных коннекции и транзакции

LoadObjectByExtConn

Назначение: Загрузка объекта с указанной коннекцией в рамках указанной транзакции

Параметры:

  • dataObjectView - Представление, по которому будет зачитываться объект.
  • dobject - Объект, который будет дочитываться/зачитываться.
  • сlearDataObject - Следует ли при зачитке очистить поля существующего объекта данных.
  • сheckExistingObject - Проверить существование встречающихся при зачитке объектов.
  • dataObjectCache - Кэш объектов.
  • connection - Коннекция, через которую будет происходить зачитка.
  • transaction - Транзакция, в рамках которой будет проходить зачитка.

Сигнатура:

public virtual void LoadObjectByExtConn(
    View dataObjectView,
    DataObject dobject, 
    bool сlearDataObject, 
    bool сheckExistingObject, 
    DataObjectCache dataObjectCache, 
    IDbConnection connection, 
    IDbTransaction transaction) 

LoadObjectsByExtConn

Назначение: Загрузка объектов с использованием указанной коннекции и транзакции

Параметры:

  • customizationStruct - Структура, определяющая, что и как грузить.
  • state - Состояние вычитки(для последующей дочитки, если используется порционное чтение, размер порции задаётся в customizationStruct.LoadingBufferSize)
  • dataObjectCache - Кэш объектов для зачитки.
  • connection - Коннекция, через которую будут выполнена зачитка.
  • transaction - Транзакция, в рамках которой будет выполнена зачитка.

Сигнатура:

public virtual DataObject[] LoadObjectsByExtConn(
    LoadingCustomizationStruct customizationStruct,
    ref object state, 
    DataObjectCache dataObjectCache,
    IDbConnection connection,
    IDbTransaction transaction)

ReadFirstByExtConn

Назначение: Получение первой порции при порционном чтении с использованием указанной коннекции и транзакции. Кроме порции объектов данных, сервис данных возвращает состояние чтения state. Это состояние передается сервису данных для получения очередных порций (см. следующий метод). Аналог предыдущего метода, но вместо настроечной структуры выборка определяется текстом запроса.

Параметры:

  • Query - Текст запроса для выборки данных
  • state - Состояние вычитки(для последующей дочитки)
  • LoadingBufferSize - размер порции
  • Connection - Коннекция, через которую будут выполнена зачитка
  • Transaction - Транзакция, в рамках которой будет выполнена зачитка

Сигнатура:

public virtual object[][] ReadFirstByExtConn(string Query, ref object State, int LoadingBufferSize, System.Data.IDbConnection Connection, System.Data.IDbTransaction Transaction)

ReadNextByExtConn

Назначение: Получение очередных порций при порционном чтении. Должен предшествовать вызов одного из двух вышеуказанных методов с получением состояния state.

Параметры:

  • state - Состояние вычитки(для последующей дочитки)
  • LoadingBufferSize - размер порции

Сигнатура:

public virtual object[][] ReadNextByExtConn(ref object State, int LoadingBufferSize)

UpdateObjectsByExtConn

Назначение: Обновить хранилище по объектам с использованием указанной коннекции и транзакции.

Параметры:

  • objects - Объекты для обновления.
  • dataObjectCache - Кеш объектов.
  • alwaysThrowException - Если произошла ошибка в базе данных, не пытаться выполнять других запросов, сразу взводить ошибку и откатывать транзакцию.
  • connection - Коннекция (не забудьте закрыть).
  • transaction - Транзакция (не забудьте завершить).

Сигнатура:

public virtual void UpdateObjectsByExtConn(ref DataObject[] objects, DataObjectCache dataObjectCache, bool alwaysThrowException, IDbConnection connection, IDbTransaction transaction)

Генерация текстов SQL-запросов

GenerateQueriesForUpdateObjects

Назначение: Генерация запросов для изменения объектов

Параметры:

  • deleteQueries - Запросы для удаление (выходной параметр)
  • deleteTables - Таблицы, из которых будет проведено удаление данных (выходной параметр)
  • updateQueries - Сгенерированные запросы для изменения (выходной параметр).
  • updateTables - Таблицы, в которых будет проведено изменение данных (выходной параметр).
  • insertQueries - Сгенерированные запросы для добавления (выходной параметр).
  • insertTables - Таблицы, в которые будет проведена вставка данных (выходной параметр).
  • tableOperations - Операции, которые будут произведены над таблицами (выходной параметр).
  • queryOrder - Порядок исполнения генерируемых запросов, задаваемый именами таблиц (выходной параметр).
  • checkLoadedProps - Проверять ли загруженность свойств.
  • processingObjects - Текущие обрабатываемые объекты (то есть объекты, которые данный сервис данных планирует подтвердить в БД в текущей транзакции). Выходной параметр.
  • dataObjectCache - Кэш объектов данных.
  • auditObjects - Список объектов, которые необходимо записать в аудит (выходной параметр). Заполняется в том случае, когда передан не null и текущий сервис аудита включен.
  • dobjects - Объекты, для которых генерируются запросы.

Сигнатура:

public virtual void GenerateQueriesForUpdateObjects(
    StringCollection deleteQueries,
    StringCollection deleteTables,
    StringCollection updateQueries,
    StringCollection updateTables,
    StringCollection insertQueries,
    StringCollection insertTables,
    SortedList tableOperations,
    StringCollection queryOrder,
    bool checkLoadedProps,
    System.Collections.ArrayList processingObjects,
    DataObjectCache dataObjectCache,
    params ICSSoft.STORMNET.DataObject[] dobjects)

В данной перегрузке дополнительно возвращается список объектов, для которых необходимо создание записей аудита:

public virtual void GenerateQueriesForUpdateObjects(
    StringCollection deleteQueries,
    StringCollection deleteTables,
    StringCollection updateQueries,
    StringCollection updateTables,
    StringCollection insertQueries,
    StringCollection insertTables,
    SortedList tableOperations,
    StringCollection queryOrder,
    bool checkLoadedProps,
    ArrayList processingObjects, 
    DataObjectCache dataObjectCache,
    List<DataObject> auditObjects,
    params ICSSoft.STORMNET.DataObject[] dobjects)

GenerateSQLSelect

Назначение: Получить запрос на вычитку данных

Параметры:

  • customizationStruct - настройка выборки
  • StorageStruct - возвращается соответствующая структура выборки

Возвращаемый результат: запрос

Сигнатура:

// 1.
public virtual string GenerateSQLSelect(LoadingCustomizationStruct customizationStruct, bool ForReadValues, out STORMDO.Business.StorageStructForView[] StorageStruct, bool Optimized)

// 2.
public virtual string GenerateSQLSelect(LoadingCustomizationStruct customizationStruct, bool Optimized)

GetLeftJoinExpression

Назначение: Получить LeftJoin выражение

Параметры:

  • subTable - имя таблицы
  • subTableAlias - псевдоним таблицы
  • parentAliasWithKey
  • subTableKey
  • subJoins
  • baseOutline

Сигнатура:

public virtual void GetLeftJoinExpression(string subTable, string subTableAlias, string parentAliasWithKey, string subTableKey, string subJoins, string baseOutline, out string FromPart, out string WherePart)

GetInnerJoinExpression

Назначение: Получить InnerJoin выражение

Параметры:

  • subTable - имя таблицы
  • subTableAlias - псевдоним таблицы
  • parentAliasWithKey
  • subTableKey
  • subJoins
  • baseOutline
  • FromPart
  • WherePart

Сигнатура:

public virtual void GetInnerJoinExpression(string subTable, string subTableAlias, string parentAliasWithKey, string subTableKey, string subJoins, string baseOutline, out string FromPart, out string WherePart)

GetJoinTableModifierExpression

Назначение: Вернуть модификатор для обращения к таблице (напр WITH (NOLOCK))

Можно перегрузить этот метод в сервисе данных-наследнике для возврата соответствующего своего модификатора. Базовый SQLDataService возвращает пустую строку.

Сигнатура:

public virtual string GetJoinTableModifierExpression()

GetINExpression

Назначение: Вернуть in выражение для where

Параметры:

identifiers - идентификаторы

Сигнатура:

public virtual string GetINExpression(params string[] identifiers)

GetIfNullExpression

Назначение: Вернуть ifnull выражение

Параметры:

identifiers - идентификаторы

Сигнатура:

public virtual string GetIfNullExpression(params string[] identifiers)

PutIdentifierIntoBrackets

Назначение: Оформить идентификатор

Параметры:

identifier - идентификатор

Возвращаемый результат: оформленный идентификатор(например в кавычках)

Сигнатура:

public virtual string PutIdentifierIntoBrackets(string identifier)

CreateJoins

Назначение: Создать join соединения

Параметры:

  • source - источник с которого формируется соединение
  • parentAlias - вышестоящий алиас
  • index - индекс источника
  • keysandtypes - ключи и типы
  • baseOutline - смещение в запросе
  • joinscount - количество соединений

Сигнатура:

public virtual void CreateJoins(STORMDO.Business.StorageStructForView.PropSource source,
    string parentAlias, int index,
    System.Collections.ArrayList keysandtypes,
    string baseOutline, out int joinscount,
    out string FromPart, out string WherePart)

CreateJoins

Назначение: Создать join соединения

Параметры:

  • source - источник с которого формируется соединение
  • parentAlias - вышестоящий алиас
  • index - индекс источника
  • keysandtypes - ключи и типы
  • baseOutline - смещение в запросе
  • joinscount - количество соединений

Сигнатура:

public virtual void CreateJoins(STORMDO.Business.StorageStructForView.PropSource source,
    string parentAlias, int index,
    System.Collections.ArrayList keysandtypes,
    string baseOutline, out int joinscount,
    out string FromPart, out string WherePart, bool MustNewGenerate)

GenerateSQLSelectByStorageStruct

Назначение: Получение SQL запроса в следующем формате

SELECT
  atr1,atr2,... atr3,
  Key1,Key2,... key3
FROM
  fromjoins

Параметры:

  • storageStruct - структура хранилища
  • AddingAdvansedField - довленные дополнительные свойства
  • AddingKeysCount - добавленниые ключи
  • addMasterFieldsCustomizer
  • addNotMainKeys
  • SelectTypesIds

Сигнатура:

// 1.
virtual public string GenerateSQLSelectByStorageStruct(STORMDO.Business.StorageStructForView storageStruct, bool addNotMainKeys, bool addMasterFieldsCustomizer, string AddingAdvansedField, int AddingKeysCount, bool SelectTypesIds)

// 2.
virtual public string GenerateSQLSelectByStorageStruct(STORMDO.Business.StorageStructForView storageStruct, bool addNotMainKeys, bool addMasterFieldsCustomizer, string AddingAdvansedField, int AddingKeysCount, bool SelectTypesIds, bool MustNewGenerate, bool MustDopSelect)

ConvertSimpleValueToQueryValueString

Назначение: Конвертация константных значений в строки запроса

Параметры:

value - значение

Сигнатура:

public virtual string ConvertSimpleValueToQueryValueString(object value)

ConvertValueToQueryValueString

Назначение: Конвертация значений в строки запроса

Параметры:

value - значение

Сигнатура:

public virtual string ConvertValueToQueryValueString(object value)

ConvertValueToQueryValueString

Назначение: Преобразование значение свойства в строку для запроса

Параметры:

  • dataobject - объект данных
  • propname - имя свойства

Сигнатура:

public virtual string ConvertValueToQueryValueString(DataObject dataobject, string propname)

LimitFunction2SQLWhere

Назначение: Преобразование функции

Параметры:LimitFunction - настроечная структура выборки

Сигнатура:

public virtual string LimitFunction2SQLWhere(STORMFunction LimitFunction, STORMDO.Business.StorageStructForView[] StorageStruct, string[] asnameprop, bool MustNewGenerate)

LimitFunction2SQLWhere

Назначение: Преобразование функции

Параметры:

LimitFunction - настроечная структура выборки

Сигнатура:

public virtual string LimitFunction2SQLWhere(STORMFunction LimitFunction)

Выполнение операций с указанием текста запроса

ReadFirst

Назначение: Вычитка первой партии данных при порционном чтении. Кроме порции объектов данных, сервис данных возвращает состояние чтения state. Это состояние передается сервису данных для получения очередных порций (см. следующий метод).Выборка определяется текстом запроса.

Параметры:

  • Query - Текст запроса для выборки данных
  • state - Состояние вычитки(для последующей дочитки)
  • LoadingBufferSize - размер порции

Сигнатура:

public virtual object[][] ReadFirst(string Query, ref object State, int LoadingBufferSize)

ReadNext

Назначение: Получение очередной порции при порционном чтении. Должен предшествовать вызов предыдущего метода с получением состояния state.

Параметры:

  • state - Состояние вычитки(для последующей дочитки)
  • LoadingBufferSize - размер порции

Сигнатура:

public virtual object[][] ReadNext(ref object State, int LoadingBufferSize)

ExecuteNonQuery

Назначение: Выполнить запрос

Параметры:

Query - текст SQL-запроса

Возвращаемый результат: количество задетых строк

Сигнатура:

public virtual int ExecuteNonQuery(string Query)

Список событий для SQLDataService

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

// Делегат для события создания команды.
public delegate void OnCreateCommandEventHandler(object sender, CreateCommandEventArgs e);

// Делегат для события при генерации SQL Select запроса (перед).
public delegate void OnGenerateSQLSelectEventHandler(object sender, GenerateSQLSelectQueryEventArgs e);

// Делегат для события при генерации SQL Select запроса (после).
public delegate void AfterGenerateSQLSelectQueryEventHandler(object sender, GenerateSQLSelectQueryEventArgs e);

// The before update objects event handler.
public delegate void BeforeUpdateObjectsEventHandler(object sender, DataObjectsEventArgs e);

// The after update objects event handler.
public delegate void AfterUpdateObjectsEventHandler(object sender, DataObjectsEventArgs e);
Событие Описание
OnGenerateSQLSelect Срабатывает перед генерацией SQL SELECT’а (пример). Обрабатывая это событие можно, например, добавить дополнительные условия, которые должны попасть в формируемый запрос.
AfterGenerateSQLSelectQuery Срабатывает после генерации SQL SELECT’а, но до вычитки данных (пример). Можно использовать для внесения изменений в сгенерированный текст запроса.
BeforeUpdateObjects Срабатывает перед обновлением объектов в базе, после отработки бизнес-серверов.
AfterUpdateObjects Срабатывает после обновления объектов в базе.
OnCreateCommand Срабатывает при создании SQL-команды (пример).

Задание CommandTimeout

Есть возможность указывать IDbCommand.CommandTimeout. Для этого можно в конфигурационном файле задать параметр:

<add key="SQLDataServiceCommandTimeout" value="60"/>

либо присвоить значение явно:

SQLDataService ds = (SQLDataService)DataServiceProvider.DataService;
ds.UseCommandTimeout = true;
ds.CommandTimeout = 60;

UseCommandTimeout нужно указывать обязательно. По-умолчанию этот флаг имеет значение false.

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

Также важно понимать, что при выполнении любой операции (чтение/обновление и т.д.) коннекция создаётся, а в конце закрывается. Т.е. последовательные LoadObjects будут выполнены в на разных System.Data.IDbConnection.

Соответственно применяться настройка времени ожидания выполнения команды будет каждый раз заново.

Смена строки соединения

SQLDataService поддерживает возможность смены строки соединения. Такая возможность, в частности, используется для работы с несколькими БД в одном приложении, описание доступно в статье.