Добрый день, всем. Очень долго выполняются запросы связанные с UpdateQuery, SelectQuery, InsertQuery. Кто-нибудь сталкивался с этим? Какие пути использовали, для нахождения проблемы?

Нравится

4 комментария
Лучший ответ

Для анализа запросов есть профайлер в mssql. Запускаете профайлере, делаете запрос из клиентской части. Смотрите какой sql для select получается в профайлере.

Еще может быть, что у вас тормозит обмен по websocket. Надо посмотреть в консоль разработчика в браузере, нет ли там ошибки с подключение к websocket.

И еще creatio требовательна к ресурсам, если вам кажется что все работает медленно, то стоит проанализировать производительность ваших серверов.

Для анализа запросов есть профайлер в mssql. Запускаете профайлере, делаете запрос из клиентской части. Смотрите какой sql для select получается в профайлере.

Еще может быть, что у вас тормозит обмен по websocket. Надо посмотреть в консоль разработчика в браузере, нет ли там ошибки с подключение к websocket.

И еще creatio требовательна к ресурсам, если вам кажется что все работает медленно, то стоит проанализировать производительность ваших серверов.

В profiler смотрел, запросы выполняются за доли миллисекунд.

Websocket работает отлично.

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

Саид Иманмагомедов,

При работе системы идет множество сложных запросов, если нет каких-то явных проблем с работой системы, значит надо наращивать мощности сервера под бд.

Вероятно, что в системе есть бизнес процесс, который срабатывает по сигналу и работает не в фоновом режиме, выполнение которого и приводит к длительному выполнению запросов InsertQuery и UpdateQuery.

Показать все комментарии
SELECT SysRoleId 
FROM SysUserInRole 
WHERE SysUserId = '7F3B869F-34F3-4F20-AB4D-7480A5FDF647'
UNION SELECT '7F3B869F-34F3-4F20-AB4D-7480A5FDF647'

Как реализовать это в Terrasoft.Core.DB.Select ??

Нравится

1 комментарий
Лучший ответ

Евгений, в Select можно использовать Union, в который передавать другой Select.

Пример такого использования есть в функции DeactivateProcessEntryPoint схемы ProcessUserTaskUtilities:

var processListenersSelect =
	new Select(userConnection)
		.Column("Id")
	.From("SysEntityCommonPrcEl")
	.Where("RecordId").IsEqual(entityIdParameter)
	.And("RecordChangeType").IsEqual(Column.Parameter(EntityChangeType.Updated));
var select =
	new Select(userConnection)
		.Column("Id")
	.From("EntryPoint")
	.Where("EntityId").IsEqual(entityIdParameter)
	.And("IsActive").IsEqual(Column.Parameter(true))
	.Union(processListenersSelect);

А получить во втором колонку-константу можно при помощи:

Column.Parameter(new Guid("7F3B869F-34F3-4F20-AB4D-7480A5FDF647"))

 

Евгений, в Select можно использовать Union, в который передавать другой Select.

Пример такого использования есть в функции DeactivateProcessEntryPoint схемы ProcessUserTaskUtilities:

var processListenersSelect =
	new Select(userConnection)
		.Column("Id")
	.From("SysEntityCommonPrcEl")
	.Where("RecordId").IsEqual(entityIdParameter)
	.And("RecordChangeType").IsEqual(Column.Parameter(EntityChangeType.Updated));
var select =
	new Select(userConnection)
		.Column("Id")
	.From("EntryPoint")
	.Where("EntityId").IsEqual(entityIdParameter)
	.And("IsActive").IsEqual(Column.Parameter(true))
	.Union(processListenersSelect);

А получить во втором колонку-константу можно при помощи:

Column.Parameter(new Guid("7F3B869F-34F3-4F20-AB4D-7480A5FDF647"))

 

Показать все комментарии

Добрый день

 

Есть интересная задача. Надо в БП по событию подключится к стороннему серверу MS-SQL и выполнить хранимую процедуру с двумя параметрами, которая вернет нам таблицу данных. Далее эту таблицу данных сохранить в кастомном разделе в системе и настроить связи с другими объектами.

Затык именно в подключении к стороннему серверу БД и вызове процедуры.

В MSSMS это выглядит как:

EXECUTE [dbo].[GetDataForCRM] @nomer,@date 

 

Нравится

8 комментариев
Лучший ответ

Добрый день!

Пробовали ли настраивать линкованные серверы? Если получится подключить сторонний сервер, то можно будет отправлять на него sql-запросы.

Добрый день!

Пробовали ли настраивать линкованные серверы? Если получится подключить сторонний сервер, то можно будет отправлять на него sql-запросы.

Указать имя сервера

Логин и пароль

Разрешить RPC для вызова ХП

Спасибо, помогло, частично. в MSSMS могу вызвать как

EXEC [LinkedServer].[LinkedDB].[dbo].[GetDataForCRM] @nomer,@date 

Как передать что надо вызывать на связанном сервере? Если я указываю полный путь процедуры, а не только имя, то получаю

EXEC [dbo].[[LinkedServer].[LinkedDB].[dbo].[GetDataForCRM]] @nomer,@date 

 

Алексей, функцию на связанном сервере запускают специальным образом, через OPENQUERY или sp_executesql, см. примеры тут.

SELECT SomeField
    FROM OPENQUERY([YOURSERVER], 'SELECT * FROM [SOMEDB].dbo.fn_SomeRemoteFunction(NULL)') tst

 

Зверев Александр,

т.е. через

StoredProcedure getDataForCRM = new StoredProcedure(UserConnection, "GetDataForCRM")
				.WithParameter("nomer", numberDoc)
				.WithParameter("date", dateDoc) as StoredProcedure;

не выйдет получить данные?

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

 

Вы можете сделать свою функцию на локальном сервере, которая, в свою очередь, запустит таким образом функцию на связанном.

 

Также не очень понятно, Вам нужно хранимую процедуру или таки функцию? Таблицу с результатами может возвращать последняя.

Показать все комментарии

Коллеги, добрый день,

 

Пожалуйста, поделитесь информацией о всевозможных причинах появления этой ошибки "При выполнении запроса произошла ошибка!" при выполнении запросов в SQL консоли.

 

Дело в том, что периодически один и тот же запрос то выполняется, то нет, в разное время нагрузки на сервер (даже когда она минимальная).

Нравится

5 комментариев
Лучший ответ

Добрый день.

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

Однако подробнее ответить на Ваш вопрос сможет только разработчик данного дополнения. Его контакты есть на маркетплейсе https://marketplace.terrasoft.ua/app/sql-executor-creatio.

Добрый день.

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

Однако подробнее ответить на Ваш вопрос сможет только разработчик данного дополнения. Его контакты есть на маркетплейсе https://marketplace.terrasoft.ua/app/sql-executor-creatio.

Интересно, а куда пропало это дополнение из Marketplace? 

Владимир Соколов,

Видимо переехало в саму систему, поскольку сейчас в коробке Creatio версии 7.18 есть в Дизайнере системы консоль для SQL

Но это предположение



Точная информация. Один из заказчиков данного функционала обнаружил уязвимость в рамках окна вывода информации после выполнения SQL-запроса, которая может быть подвергнута атакам. В связи с этим данную утилиту убрали из Маркетплейса.

Ирина Кузина пишет:

Интересно! А где именно? Что-то я не нахожу  

Владимир Соколов,

У меня данная плашка появляется только при переводе платформы в режим разработки в файловой системе, вместе с пунктами очистки кэша Redis и перезапуска пула приложения:







Прошлое сообщение отредактировала в связи с получением информации по данному вопросу)

Показать все комментарии

Добрый день!



Планирую интеграцию одного приложения с Creatio CRM через внешний API на OData4.

Читаю документацию, и вижу, что любую сущность можно получить через отдельный запрос. Но изначально система не знает какие сущности могут быть в системе, и чтобы получить их список нужно выполнить SQL-запрос (по инстркуции):

 

для MySQL

SELECT * FROM INFORMATION_SCHEMA.TABLES

для Oracle

SELECT * FROM ALL_TABLES

для PostgreSQL

SELECT table_name FROM information_schema.tables

 

У меня есть только данные для авторизации юзера через OData4, и этот запрос мне никак не выполнить.



Есть ли какой-то способ через внешний API получить список всех таблиц?

Нравится

5 комментариев
Лучший ответ

Павел, можно ещё

https://{server}/0/odata/

Так будет результат в  JSON.

 

Либо воспользоваться информацией из таблицы SysSchema, которая тоже доступна по OData. За объекты отвечает EntitySchemaManager, получить список можно с таким фильтром:

https://{server}/0/odata/SysSchema?$filter=ManagerName%20eq%20%27EntitySchemaManager%27

А вариант с выбором из базы не очень подходит, поскольку зависит от платформы, плюс не все таблицы в базе связаны с объектами конфигурации и могут быть доступны по OData. И наоборот, часть объектов сделаны не на основе table, а по view.

Нашел сам



Запрос на 

https://{server}/0/odata/$metadata

возвращает внутри <Schema Namespace="Terrasoft.Configuration.OData" xmlns="http://docs.oasis-open.org/odata/ns/edm"> все сущности

Павел, можно ещё

https://{server}/0/odata/

Так будет результат в  JSON.

 

Либо воспользоваться информацией из таблицы SysSchema, которая тоже доступна по OData. За объекты отвечает EntitySchemaManager, получить список можно с таким фильтром:

https://{server}/0/odata/SysSchema?$filter=ManagerName%20eq%20%27EntitySchemaManager%27

А вариант с выбором из базы не очень подходит, поскольку зависит от платформы, плюс не все таблицы в базе связаны с объектами конфигурации и могут быть доступны по OData. И наоборот, часть объектов сделаны не на основе table, а по view.

Зверев Александр, Спасибо! А метадату конкретной сущности как получить? 

Требуется узнать какие поля у модели.

В https://{server}/0/odata/$metadata всё есть.

Pavel Buev,

Добрый день Павел, нашли решение получение метадаты конктретной сущности? ищу рещение такой же проблемы

Показать все комментарии

Добрый день, подскажите, как можно написать подобный запрос на esq? Желательно на стороне сервера. Смотрел в сторону addAggregationSchemaColumn, но там можно либо посчитать количество, либо применить min, max и т.п, а эти функции работают только с числовыми полями.

select

(select top 1 Number from ContactCommunication where ContactId = c.Id and CommunicationTypeId = 'EE1C85C3-CFCB-DF11-9B2A-001D60E938C6')

from Contact c

Нравится

3 комментария
Лучший ответ

 Запрос в скобках:

var esq = new EntitySchemaQuery(userConn.EntitySchemaManager, "ContactCommunication");
esq.AddColumn("Number");
esq.RowCount = 1;
esq.Filters.Add(esq.CreateFilterWithParameters(
	FilterComparisonType.Equal,
	"ContactId ", contactId));
esq.Filters.Add(esq.CreateFilterWithParameters(
	FilterComparisonType.Equal,
	"CommunicationTypeId", "EE1C85C3-CFCB-DF11-9B2A-001D60E938C6"));
var collection = esq.GetEntityCollection(userConn);

 

 Запрос в скобках:

var esq = new EntitySchemaQuery(userConn.EntitySchemaManager, "ContactCommunication");
esq.AddColumn("Number");
esq.RowCount = 1;
esq.Filters.Add(esq.CreateFilterWithParameters(
	FilterComparisonType.Equal,
	"ContactId ", contactId));
esq.Filters.Add(esq.CreateFilterWithParameters(
	FilterComparisonType.Equal,
	"CommunicationTypeId", "EE1C85C3-CFCB-DF11-9B2A-001D60E938C6"));
var collection = esq.GetEntityCollection(userConn);

 

Литвинко Павел, спасибо! Попробую. Только не разбираясь в деталях, увидел проблему, что в таком случае в выборку не по попадут контакты с незаполненным полем, потому запрос не подойдет.

В идеале нужно получить поля из Контакта и поле из средств связи (в том числе пустое)

Павел, такой результат из таблицы средств связи получить не получится, ведь там нет записей о контактах без средств связи.

В Вашем случае нужно будет действовать наоборот, выбирать из таблицы Contact с добавлением колонок из таблицы детали средств связи, таких как [ContactCommunication:Contact:Id].CommunicationType и [ContactCommunication:Contact:Id].Number, по таким же колонкам можно и накладывать фильтр.

Показать все комментарии

Добрый день, при попытке слияния двух контаков, если у проигравшего есть заказ, то процесс дедупликации падает с ошибкой: 

System.Data.SqlClient.SqlException (0x80131904): Конфликт инструкции DELETE с ограничением REFERENCE "FKZt10BIrUNMXjPYmQeSNwKs8aI". 

Конфликт произошел в базе данных "ClarinsInstall", таблица "dbo.Order", column 'ContactId'.

При отладке не увидела ContactId, среди ключей таблицы Order, по которым идет перепривязка данных (есть только CreatedById и OwnerId),

подскажите, с чем это может быть вызвано?

Нравится

3 комментария
Лучший ответ

Зверев Александр пишет:

Проверьте Order в дизайнере объектов, там должно быть такое справочное поле. А если нет, то было и его удалили в объекте, но по какой-то причине осталось в базе (возможно, объект не скомпилировали).

Если проблема, действительно, в этом, то нужно не выполнять обновление конкретной записи в Order, а определиться с необходимостью наличия поля Contact в Order и в зависимости от принятого решения либо добавить в entity schema Order данное поле и скомпилировать схему, если его нет, либо удалить из таблицы в базе данных, если оно не нужно.

Иначе проблема может воспроизвестись при следующем слиянии дублей.

Это как раз и значит наличие записи в Order, ссылающееся полем ContactId на сливаемый контакт. Проверьте Order в дизайнере объектов, там должно быть такое справочное поле. А если нет, то было и его удалили в объекте, но по какой-то причине осталось в базе (возможно, объект не скомпилировали). В таком случае, если есть возможность, подключитесь к БД, найдите эту запись и замените значение ContactId на null.

Зверев Александр пишет:

Проверьте Order в дизайнере объектов, там должно быть такое справочное поле. А если нет, то было и его удалили в объекте, но по какой-то причине осталось в базе (возможно, объект не скомпилировали).

Если проблема, действительно, в этом, то нужно не выполнять обновление конкретной записи в Order, а определиться с необходимостью наличия поля Contact в Order и в зависимости от принятого решения либо добавить в entity schema Order данное поле и скомпилировать схему, если его нет, либо удалить из таблицы в базе данных, если оно не нужно.

Иначе проблема может воспроизвестись при следующем слиянии дублей.

Кстати, не уверен, что повторное добавление поля в объект пройдёт успешно без последствий. У колонки в базе прописывается GUID в Extended Properties, он будет уже другим.

Показать все комментарии

Всем привет.

Ввиду не внятности документации прошу помощи.

Как составить такой запрос используя ESQ на клиенте?

SELECT account.UsrINN,(SELECT TOP(1) ModifiedOn FROM Activity activity WHERE activity.AccountId=account.Id ORDER BY ModifiedOn) AS LastComunicationDate  FROM Account account  WHERE account.UsrINN = '7730616959' 

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

Изображение удалено.

 

 

Нравится

9 комментариев
Лучший ответ

Последовский Роман,

А так?

var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "Account" });
esq.addColumn("UsrINN");
esq.addAggregationSchemaColumn("[Activity:Account].ModifiedOn", 5, "MaxModifiedOn");
esq.filters.addItem(esq.createColumnFilterWithParameter(3, "UsrINN", "7730616959"));
esq.getEntityCollection(function (result) {
	if (result.success &amp;&amp; result.collection.getCount() &gt; 0) {
		result.collection.collection.each(function(item) {
			//some logic
		}, this);
	}
}, this);

 

Роман, приветствую,

А у вас проблема в подзапросе или в сортировке?

Есть в сортировке, то возможно вам поможет вот это: https://community.terrasoft.ru/questions/entityschemaquery-order

Если в подзапросе, то можно

1. Сделать один запрос, а в его колбэке (или в цикле foreach, если это C# сделать еще один запрос).

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

На клиенте? Тогда как-то так:

var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "Activity" });
 
esq.addColumn("Account.UsrINN", "AccountINN");
var column = esq.addColumn("ModifiedOn");
column.orderDirection = Terrasoft.OrderDirection.ASC; //asc по modifiedOn
 
esq.rowCount=1; //top1
 
esq.filters.addItem(esq.createColumnFilterWithParameter(3, "Account.UsrINN", "7730616959")); //фильтр по INN
 
esq.getEntityCollection(function (result) {
	if (result.success &amp;&amp; result.collection.getCount() &gt; 0) {
		var item = result.collection.getByIndex(0);
		var INN = item.get("AccountINN");
		var modOn = item.get("ModifiedOn");
	}
}, this);

 

Мне кажется, тут сам SQL-запрос надо вывернуть наизнанку:

SELECT max(ModifiedOn) FROM Activity activity
left join Account account on activity.AccountId=account.Id 
WHERE account.UsrINN = '7730616959'

То есть получим запрос с одной колонкой и одним фильтром по прямой связи. Заодно вместо TOP 1 можно просто максимум при помощи addAggregationSchemaColumn. А затем фильтруем, применив createColumnFilterWithParameter к колонке «Account.UsrINN».

 

Спасибо большое, вариант Данилы работает, но

Затык как раз в том что мне нужно вывести именно список контрагентов(UsrINN), а уже к каждому из них привязать дату последней работы с активностью.

 

 

 

Судя по исходному вопросу, код контрагента известен и равен 7730616959, следовательно, в списке всегда будет одна строка. Если таких номеров несколько, можно получить этим кодом в цикле для каждого.

Это часть системы поиска дублей.

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

ИНН:123

10 контрагентов, но у 5ти из них есть активности.

Если я сначала полезу в таблицу активности, то мне выведется на экран только 5ть контрагентов, а реально их 10.

В самом начале я указал именно тот SQL запрос, который нужно изобразить с помощью ESQ.

Конечно можно это сделать двумя циклами, но хочется понять можно ли это сделать одним запросом

 

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

Последовский Роман,

А так?

var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "Account" });
esq.addColumn("UsrINN");
esq.addAggregationSchemaColumn("[Activity:Account].ModifiedOn", 5, "MaxModifiedOn");
esq.filters.addItem(esq.createColumnFilterWithParameter(3, "UsrINN", "7730616959"));
esq.getEntityCollection(function (result) {
	if (result.success &amp;&amp; result.collection.getCount() &gt; 0) {
		result.collection.collection.each(function(item) {
			//some logic
		}, this);
	}
}, this);

 

Варфоломеев Данила,

Памятник поставить мало! Спасибо)

Показать все комментарии

Интересует возможность разнесения базы на файловые группы для разнесения групп на разные жёсткие диски (разный объем и скорость).

Есть ли в ВРМ встроенная возможность создавать определенные таблицы, например xxxFile на определенной файловой группе? И вообще, есть ли возможность управлять созданием таблиц на файловых группах?

Есть ли у кого-то положительный опыт разнесения базы на ФГ?

Нравится

1 комментарий

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

Показать все комментарии

Всем доброго времени суток.
Хотелось бы узнать если ли возможность в элемент бизнес-процесса "Задание-сценарий" вставить запрос к базе данных и если есть, то можно хоть самый простой пример c Select.

Нравится

2 комментария

Сергей, такая возможность есть.
Пример можно посмотреть на академии в этой статье.

Спасибо Наталия. Буду разбираться.

Показать все комментарии