Можно с помощью планировщика запланировать время выполнения самого процесса. http://www.community.terrasoft.ru/forum/topic/12917
Можно запланировать время выполнения элемента с помощью Таймера.
Нужно понимать, что в этих случаях необходимо отталкиваться от какого-то времени или события.
Можно добавить активность с типом звонок с помощью элемента Добавление данных – указать дату начала активности.
Есть некоторый элемент- действие "Чтение данных", который считывает записи из таблицы и помещает в некоторую результирующую коллекцию ResultEntityCollection.
Как обратиться к этой коллекции из кода C# в действии "Задание- сценарий"?
В новом движке процессов работать можно только с параметрами процесса, либо напрямую с параметрами элементов, на которые настроен маппинг.
Пример решения задачи во вложении. scripttaskmapping.txt
Согласно этому сайту, мой коллега хотел написать следующее:
1. Создать параметр процесса типа Строка - TestParam.
2. В значение параметра указать [#Read data 1.First item of resulting collection#].GetTypedColumnValue("Name")
3. В элементе Задание-сценарий работать с параметром.
var contactFullName = Get("TestParam");
Есть некоторый элемент- действие "Чтение данных", который считывает записи из таблицы
и помещает в некоторую результирующую коллекцию ResultEntityCollection.
Далее я определяю параметр AggregateCollection, в котором будет сохраняться данная коллекция и через который я буду обращаться к ней из кода C#:
Значение данного параметра:
[#Чтение данных из таблицы контракты.Результирующая коллекция#]
В элементе "Задание- сценарий" я пытаюсь получить данный параметр:
var entityCollection = Get("AggregateCollection");
foreach (var entity in entityCollection) {
Console.WriteLine(entity);
}
Однако на выходе ничего нет. Конфигурация компилируется без ошибок.
Как правильно обратиться к коллекции объектов EntityCollection?
Алексей, спасибо за Ваш ответ! Не сериализуется - в том смысле, что должна или не должна? Чекбокс "Сериализировать значение" проставлен по- умолчанию для элемента "Чтение данных". В нем я по определенному фильтру считываю записи. Когда данный элемент добавляется в дизайнер БП, для него создаются ряд параметров, в т.ч. ResultEntityCollection. Все параметры - не редактируемые. Чтобы обратиться к этой коллекции ResultEntityCollection из C# я создаю в параметрах процесса параметр AggregateCollection с типом "Коллекция объектов (EntityCollection)". Может, коллекцию нужно привязать к моему параметру через формулу?
Добрый день! у меня проблема с программой, я создаю файл dataset для своего fast report, но при добавлении полей справочника программа закрывается, Microsoft Script Debugger у меня установлен, данную ошибку не отслеживает, клиентская часть работает вроде нормально, помогите решить данную проблему.
создаю сервис dataset, и добавляю в нем поля типа справочник, у справочнику указываю источник из другого dataset, родительського, тот, который нужен, он добавляется, затем программа вылетает ((, но потом зайти на dataset невозможно, программа вылетает при попытке зайти на dataset ((.
1) Вы добавляете поля в тот датасет, который находится в архиве?
2) Какие именно поля Вы добавлете, что указываете в качестве источника?
3) Возникает ли эта ошибка, если Вы пытаетесь добавить такое же поле в другой датасет или только в этот?
Эта информация нужна, чтобы установить причину ошибки.
1) нет, у свой созданый датасет
2) добавляю поле customer, типу справочника, указиваю в нем источник ds_Account, дальше сохраняю, пробую вернуться и выбивает ошибку
3) да, возникает, уже все перепробовал
1) Сервис в архиве тоже назвается ds_TestReport и содержит те же поля. Он у меня открывается без ошибок.
2) Для анализа проблемы выложите ещё сервис отчета fr_TestReport (также, если, как Вы утвержаете, select query и dataset отличаются от тех, которые находятся в предыдущем комментарии в архиве, добавьте и их).
Также рекоммендую обратиться в службу поддержки и запросить последние бинарные файлы для обновления текущей версии Terrasoft.
Здравствуйте, изучил тему по ссылке. В частности последний пост.
Возник ряд вопросов:
- Как правильно использовать dbExecutor для избежания утечки памяти?
- В каких именно случаях нужно пользоваться указанным в теме подходом?
- Всегда ли нужно оборачивать методы Execute() и ExecuteScalar() классов Select, Insert, Update в using, если нет, то в каких случаях это не обязательно?
"Венжик Игорь" написал:Часто возникает ситуация когда необходимо сделать специфичечкий запрос к БД, который невозможно или сложно воспроизвести с помощью бизнес-сущностей. Например запросы к таблицам прав доступа, к системным таблицам. (Не законченная статья...)
В таких случая необходимо строить кастомные запросы:
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("Киев"))
Получение значения из первой строки, первого столбца выборки
Есть два способа
var name = select.ExecuteScalar();
или
string name;
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
name = select.ExecuteScalar(dbExecutor);
}
Оба способа вернут один и тот же результат. Если вы выполняете одиночный запрос тогда используйте первый вариант, он является оберткой над вторым. Второй вариант, с передачей dbExecutor-а, будет полезен если выполнять несколько запросов к БД в рамках одной транзакции.
Получение списка значений:
List names = new List();
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
using (var reader = select.ExecuteReader(dbExecutor)) {
while(reader.Read()) {
int columnOrdinal = reader.GetOrdinal("Name");
names.Add(reader.GetString(columnOrdinal));
}
}
}
Выполнение запроса в рамках транзакции:
Оба запроса в базу будут выполнены в рамках транзакции и в случае свала транзакция откатится.
List names = new List();
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.
Методы Execute() и ExecuteScalar() классов Select, Insert, Update в using оборачивать не нужно.
Для Select-ов ExecuteScalar или Execute, который принимает анонимный метод - также не стоит оборачивать в using.
Для Select-а, который использует конструкцию List names необходимо использовать Using:
List names = new List();
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
using (var reader = select.ExecuteReader(dbExecutor)) {
while(reader.Read()) {
int columnOrdinal = reader.GetOrdinal("Name");
names.Add(reader.GetString(columnOrdinal));
}
}
}
Добрый день! Давно и сильно интересует вопрос, каким образом обернуть в транзакцию событийный процесс объекта при сохранении/удалении? Для гарантированной согласованности данных в разных сущностях, когда изменения в одном объекте влекут изменения в другом связанном.
Столкнулся с некоторыми трудностями чтения из базы данных с помощью объекта DBExecutor.
Есть простой кастомный запрос:
var userConnection = Get("UserConnection");
Guid addedRecordId = Get("addedRecordId");
var selectQuery = new Select(userConnection)
.Column("UsrName")
.From("UsrDebt").As("ud")
.Where("UD", "Id")
.IsEqual(Column.Parameter(addedRecordId));
var userConnection = Get("UserConnection");
Guid addedRecordId = Get("addedRecordId");
var selectQuery =
new Select(userConnection)
.Column("UsrName")
.From("UsrDebt").As("ud")
.Where("UD", "Id")
.IsEqual(Column.Parameter(addedRecordId));
// Выполнение запроса к базе данных и получение результирующего набора данных.
using (DBExecutor dbExecutor = userConnection.EnsureDBConnection())
{
using (IDataReader reader = selectQuery.ExecuteReader(dbExecutor)) // строка 48
{
while (reader.Read())
{
// Обработка результатов запроса.
}
}
}
Получаю такую ошибку:
Как я могу получить значения из базы данных с помощью объекта DBExecutor?
Есть некоторый простой бизнес- процесс, инициируемый событием- сигналом "Добавление записи в таблицу". При каждом добавлении записи я получаю ее уникальный идентификатор, например -
F6F4725A-C7C6-4AA2-BE50-E4878ACB7D4B
Я выполняю простой запрос из MS SQL Server Management Studio -
SELECT
UsrInDebtId
FROM
UsrDebt
WHERE
Id='F6F4725A-C7C6-4AA2-BE50-E4878ACB7D4B';
Получаю какой- то результат.
Аналогично из кода C#
...
myConnection.Open();
SqlCommand myCommand = new SqlCommand("...", myConnection);
SqlDataReader myReader = myCommand.ExecuteReader();
while (myReader.Read()) {
...
}
...
Уникальный идентификатор я сохраняю в параметре addedRecordId -
Guid addedRecordId = Get("addedRecordId");
Далее я хочу использовать класс Select из пространства имен Terrasoft.Core.DB -
Может быть, существует возможность получить строковое представление уникального идентификатора из события- сигнала и далее уже программно создать Guid, который и передать в предикат?..
Есть некоторый простой бизнес- процесс, инициируемый событием- сигналом "Добавление записи в таблицу".
Например:
В бизнес- процессе участвует действие "Задание сценарий", в которое я хочу передать Guid добавленной записи для последующих расчетов на основе этого переданного идентификатора, т.е. как- то считать его с того события, которым этот процесс был инициирован.
Как это сделать? Насколько я понимаю, нужно добавить параметр, но как записать в него Guid той записи, которая добавляется?
У стартового сигнала есть параметр "Идентификатор записи" (RecordId). Создайте параметр процесса NewID с типом "Уникальный идентификатор". Используйте элемент "Формула" для передачи параметра StartSignal.RecordId в созданный Вами параметр NewID.
Используйте в задании-сценарии следующий код, чтобы получить значение, которое хранится в параметре NewID:
Id = Get<Guid>("NewID")
В итоге в параметре элемента "Задание-сценарий" будет установлено Id стартового сигнала.