Сервис данных, работающий с реляционными хранилищами.
Является абстрактным классом, от него наследуется
Основные возможности 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
Назначение: Обновить хранилище по объектам с использованием указанной коннекции и транзакции.
alwaysThrowException=true, всегда взводится ошибка. Иначе, выполнение продолжается. Однако, при этом есть опасность преждевременного окончания транзакции, с переходом для остальных запросов режима транзакционности в autocommit. Проявлением проблемы являются ошибки вроде: The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.Параметры:
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- псевдоним таблицыparentAliasWithKeysubTableKeysubJoinsbaseOutline
Сигнатура:
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- псевдоним таблицыparentAliasWithKeysubTableKeysubJoinsbaseOutlineFromPartWherePart
Сигнатура:
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- добавленниые ключиaddMasterFieldsCustomizeraddNotMainKeysSelectTypesIds
Сигнатура:
// 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 поддерживает возможность смены строки соединения. Такая возможность, в частности, используется для работы с несколькими БД в одном приложении, описание доступно в статье.