Сервис данных, работающий с реляционными хранилищами.
Является абстрактным классом, от него наследуется
Основные возможности 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
- псевдоним таблицы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
поддерживает возможность смены строки соединения. Такая возможность, в частности, используется для работы с несколькими БД в одном приложении, описание доступно в статье.