Вопрос

Реализовала такой запрос:

var esqKit = new EntitySchemaQuery(userConnection.EntitySchemaManager, "Kit");
                EntitySchemaQuery kitsCountSubQuery;
                esqKit.AddColumn("Id", AggregationTypeStrict.Count, out kitsCountSubQuery);
                esqKit.Filters.Add(esqKit.CreateFilterWithParameters(FilterComparisonType.Equal, "BTContactPatient",
                    patientId));
                EntityCollection kitsCollection = esqKit.GetEntityCollection(userConnection);

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

Как называется эта колонка и как правильно обратиться к kitsCountSubQuery, чтобы получить результат запроса?

У меня такой же вопрос

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

Алла, нужно запомнить объект-результат AddColumn в переменную, а потом посмотреть её Name. Как тут:

var gridPageEntitySchemaQuery = (EntitySchemaQuery)GridPageEntitySchemaQuery;
var monthColumn = gridPageEntitySchemaQuery.AddColumn(gridPageEntitySchemaQuery.CreateMonthFunction(columnName));
var yearColumn = gridPageEntitySchemaQuery.AddColumn(gridPageEntitySchemaQuery.CreateYearFunction(columnName));
var aggregationValueColumn = gridPageEntitySchemaQuery.AddColumn(
	gridPageEntitySchemaQuery.CreateAggregationFunction(AggregationTypeStrict.Count,
	gridPageEntitySchemaQuery.RootSchema.PrimaryColumn.Name));
EntitySchemaQueryFilterCollection filters = gridPageEntitySchemaQuery.Filters;
filters.Add(gridPageEntitySchemaQuery.CreateFilterWithParameters(FilterComparisonType.IsNotNull,columnName));
var entityCollection = gridPageEntitySchemaQuery.GetEntityCollection(Page.UserConnection);
string dateName = string.Empty;
int month = 0;
foreach (var item in entityCollection) {
	var aggregationValue = item.GetTypedColumnValue<double>(aggregationValueColumn.Name);
	month = item.GetTypedColumnValue<int>(monthColumn.Name);
	dateName =  item.GetTypedColumnValue<string>(yearColumn.Name)+ "-" +(month < 10 ? "0" + month.ToString() : month.ToString());
	series.Add(dateName, aggregationValue);
}

 

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

Спасибо за подсказку - все получилось.

Если интересно, то данная колонка называется просто 'Column'.

А если вторую сделать?

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

var esqOpportunity = new EntitySchemaQuery(userConnection.EntitySchemaManager, "Opportunity");
esqOpportunity.AddColumn("Id");
var opportunityCollection = esqOpportunity.GetEntityCollection(userConnection);
Guid opportunityId = Guid.Empty;
if (opportunityCollection.Count > 0) {
    opportunityId = opportunityCollection[0].GetTypedColumnValue<Guid>("Id");
}

Почему при попытке получить значение opportunityCollection[0].GetTypedColumnValue<Guid>("Id") выдается ошибка: Value "Id" was not found?

В профайлере в запросе Id записи выбирается.

Если написать такой код:

var esqOpportunity = new EntitySchemaQuery(userConnection.EntitySchemaManager, "Opportunity");
esqOpportunity.AddAllSchemaColumns();
var opportunityCollection = esqOpportunity.GetEntityCollection(userConnection);
Guid opportunityId = Guid.Empty;
if (opportunityCollection.Count > 0) {
    opportunityId = opportunityCollection[0].GetTypedColumnValue<Guid>("Id");
}

В этом случае ошибки не возникает.

Можно ли получить Id записи каким-то другим образом, но чтобы был первый вариант с выбором одной колонки?

У меня такой же вопрос

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

А если так 

var esqOpportunity = new EntitySchemaQuery(userConnection.EntitySchemaManager, "Opportunity");
var colidName = esqOpportunity.AddColumn("Id");
var opportunityCollection = esqOpportunity.GetEntityCollection(userConnection);
Guid opportunityId = Guid.Empty;
if (opportunityCollection.Count > 0) {
    opportunityId = opportunityCollection[0].GetTypedColumnValue<Guid>(colidName.Name);
}

 

А если так 

var esqOpportunity = new EntitySchemaQuery(userConnection.EntitySchemaManager, "Opportunity");
var colidName = esqOpportunity.AddColumn("Id");
var opportunityCollection = esqOpportunity.GetEntityCollection(userConnection);
Guid opportunityId = Guid.Empty;
if (opportunityCollection.Count > 0) {
    opportunityId = opportunityCollection[0].GetTypedColumnValue<Guid>(colidName.Name);
}

 

Григорий Чех,

Спасибо за вариант решения. Так, конечно, работает.

Интересно, что работает еще и так:

opportunityCollection[0].GetTypedColumnValue<Guid>("Id1").

Но почему "Id1" (в запросе же колонка называется "Id")???

 

Видимо, так создаётся вторая колонка Id в запросе вроде «select id, id as id1».

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

Но в профайлере ж запрос создается в таком виде:

SELECT
    [Opportunity].[Id] [Id]
FROM
    [dbo].[Opportunity] [Opportunity] WITH(NOLOCK)

Алла Савельева,

ESQ использует Id для внутрених целей

esqOpportunity.PrimaryQueryColumn.IsAlwaysSelect = true; Вот так пишите и сможете получать Id, чтобы не писать Id1

Можно еще так: 
                opportunityId = opportunityCollection.First().PrimaryColumnValue;
           

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Не могу нигде найти, каким образом возможно получить top N в запросе на JavaScript.

Везде только примеры на С#.

У меня такой же вопрос

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

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

Спасибо!

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Похожая задача и похожая проблема ( https://community.terrasoft.ru/questions/zapros-ne-vozvrasaet-znacenie ). Используя запрос:

var vip = 0;
var recordId = item.get("Id");
var esqCase = Ext.create("Terrasoft.EntitySchemaQuery", {
rootSchemaName: "Case"
});
esqCase.addColumn("UsrVIPobr");
esqCase.getEntity(recordId, function(result) {
if (result.success) {
vip = result.entity.get("UsrVIPobr");
}
}, this);

Получаю корректный Id (по базе находится нужное обращение с нужным id и полем UsrVIPObr). В карточке обращения есть логическое поле UsrVIPobr (1 или 0), но почему-то переменная vip не меняется. Прошу помочь разобраться. 

У меня такой же вопрос

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

Быстров Сергей,

Добро пожаловать в мир async вычислений, коллбеков и промисов)

Вам надо весь код(который за скриншотом) перенести в коллбек-функцию getEntity. грубо говоря:

var vip=null;
esq.getEntity(id, function(p) {
     //тут vip будет не null
     var vip=...;
 
     if (vip) {....}
}, this);
//тут vip все ещё null, следующие строки кода отработают ДО результата функции getEntity
var a = ...;
....

 

То, что у вас скриншот обрывается на esq.getEntity - уже подозрительно :)

Вы используете переменную vip после выполнения getEntity?

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

Да, используется для сравнения с константой

Там же асинхронное выполнение. В getEntity добавляется функция, которая запустится где-то потом, а код пошёл выполняться дальше.

Быстров Сергей,

Добро пожаловать в мир async вычислений, коллбеков и промисов)

Вам надо весь код(который за скриншотом) перенести в коллбек-функцию getEntity. грубо говоря:

var vip=null;
esq.getEntity(id, function(p) {
     //тут vip будет не null
     var vip=...;
 
     if (vip) {....}
}, this);
//тут vip все ещё null, следующие строки кода отработают ДО результата функции getEntity
var a = ...;
....

 

А есть какие-то безболезненные способы заставить работать код в синхронном режиме?

Быстров Сергей,

нет. только упаковать всё в Terrasoft.chain (те же коллбеки, только в более удобоваримом виде)

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день.

Подскажите как организовать фильтр в клиентской esq по агрегированным данным. Например вот есть такая агрегирующая колонка

		putNestingColumn: function(esq) {
			var aggregationColumn = this.Ext.create("Terrasoft.AggregationQueryColumn", {
				aggregationType: Terrasoft.AggregationType.COUNT,
				columnPath: "[OpportunityProductInterest:NrbParent].Id"
			});
			if (!esq.columns.contains("HasNesting")) {
				esq.addColumn(aggregationColumn, "HasNesting");
			}
		},

А требуется, чтобы выводились только те записи, у которых есть подчиненные записи (в этой колонке значение > 0).

 

Есть метод createFilter, в который необходим передать объект класса Terrasoft.BaseExpression или наследника, но непонятно как в таком случае указать колонку, по которой считать?

		var leftExpression = Ext.create("Terrasoft.FunctionExpression", {
			functionType: Terrasoft.FunctionType.AGGREGATION,
			aggregationType: Terrasoft.AggregationType.COUNT,
	        aggregationEvalType: Terrasoft.AggregationEvalType.ALL
	});

 

У меня такой же вопрос

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

Мне кажется, в этом случае надо надо не createFilter, а createExistsFilter. Как тут.

createExistsFilter(columnPath)

Создает экземпляр Exists-фильтра для сравнения типа [Существует по заданному условию] и устанавливает в качестве проверяемого значения выражение колонки, расположенной по заданному пути.

Да я, к сожалению, привел нерелевантный пример задачи. Если мне нужно, чтобы значения было не более 0 (в этом случае Exists поможет), а более, скажем, 5.

PS В приведенной статье речь все же идет о серверной esq

В примере по ссылке (не комментариях) используется клиентская. Если же нужно сравнивать с числом, можно попробовать подставлять выражение колонки в createColumnFilterWithParameter.

createColumnFilterWithParameter(comparisonType, columnPath, paramValue)

Создает экземпляр Compare-фильтра для сравнения колонки с заданным значением.

comparisonType Terrasoft.ComparisonType Тип операции сравнения.

columnPath String Путь к проверяемой колонке относительно корневой схемы rootSchema.

paramValue Mixed Значение параметра.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день,

У меня такой вопрос, есть представление VwExample, я добавил SQL сценарий на его изменение через ALTER VIEW, добавил пару колонок. При выборке через MSSQL Server все нормально выбирает.
Однако в коде почему то говорит 
Terrasoft.Common.ItemNotFoundException: Значение с именем "TestColumn" не найдено

 

Выбираю следующим образом 
 

var esqActivity = new EntitySchemaQuery(userConnection.EntitySchemaManager, "VwExample");
esqActivity.AddAllSchemaColumns(true);
var entities = esqActivity.GetEntityCollection(userConnection);

Значения получаю так: 

foreach (var entity in entities)
{
    var test = activity.GetTypedColumnValue<Guid>("TestColumn");
 
}

Такое ощущение что в BPM хранится предыдущее представление до его изменения, хотя в базе данных при Select * from VwExample" выводит все колонки, в том числе TestColumn. Я что то забываю?

У меня такой же вопрос

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

ESQ берёт информацию о колонках не из самой таблицы или view в базе, а из объекта в конфигурации. Соответственно, нужно открыть дизайнер объекта и добавить и там все новые колонки.

Войдите или зарегистрируйтесь, чтобы комментировать

Добрый день.
При попытке сохранить новую запись в бд через esq возникает ошибка на методе Save():

"Ссылка на объект не указывает на экземпляр объекта..    в Terrasoft.Core.DB.Select.GetSqlText()"

Код:

var schema = UserConnection.EntitySchemaManager.GetInstanceByName("OrderProduct");
			var esqEntity = schema.CreateEntity(UserConnection);
			esqEntity.SetColumnValue("Id", entity.BpmId);
            ....
            esqEntity.SetColumnValue("CurrencyId", entity.CurrencyId);
            esqEntity.UseAdminRights = false;
            esqEntity.Save();

 

У меня такой же вопрос

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

Сообщение «Ссылка на объект не указывает на экземпляр объекта» означает, что в C#-коде конфигурации или ядра в какое-то поле попадает Null, а с ним пытаются работать как с объектом. Например, обращаться к его полям и методам. Не видя полного кода и стека сложно сказать точно, где именно.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

select ad.id, ad.Address

from 
  AddressType at, 
  AccountAddress ad

where 
    ad.AccountId = 'e308b781-3c5b-4ecb-89ef-5c1ed4da488e'
    and at.Id = ad.AddressTypeId
    --and at.Name = 'Собеседования' 
    and at.Name = 'Места работы'

var select = this.Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "AccountAddress" });
                    select.addColumn("Id");
                    select.addColumn("Address");
                    select.filters.add("filterByAccountWork1",
                        select.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
                            "Account", this.get("AccountId")));
                    select.filters.add("filterByAccountWork2",
                        select.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
                            "AddressType", "Места работы"));
                            /* вот тут где-то синтакс ошибка
                    select.filters.add("filterByAccountWork3",
                        select.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
                            "[AccountAddress:AddressType].Id",
                            "[AccountAddress.AddressType].Id"));
                            */

 

У меня такой же вопрос

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

Добрый день

А вам точно нужно декартовое произведение? Это будет долго работать

Чем не подойдет?

select 
   ad.id, 
   ad.Address 
from 
  AccountAddress ad
  inner join AddressType at on at.Id = ad.AddressTypeId
where 
    ad.AccountId = 'e308b781-3c5b-4ecb-89ef-5c1ed4da488e'
    --and at.Name = 'Собеседования' 
    and at.Name = 'Места работы'

и в этом случае все гораздо проще, и данных в разы меньше

 

Артем Гура,

Привет, Да, так лучше намного будет, а как это сделать на esq? :) Запутался, все время синтакс еррор в консоли. Пытался сделать по 

https://academy.terrasoft.ru/documents/technic-sdk/7-12/postroenie-pute… но пока не смог :), прошу помощи

QArt,

Что-то вроде этого:

var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
    rootSchemaName: "AccountAddress"
});
esq.addColumn("Id");
esq.addColumn("Address");
var filterGroup = Ext.create("Terrasoft.FilterGroup");
filterGroup.logicalOperation = Terrasoft.LogicalOperatorType.AND;
filterGroup.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "Account", ''));
filterGroup.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "=[AddressType:Id:AddressTypeId].Name", 'Собеседования'));
esq.filters.addItem(filterGroup);
esq.getEntityCollection(...)

 

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

getFullAddressFromVacancy: function (Id) {
                        var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
                            rootSchemaName: "AccountAddress"
                        });
                        esq.addColumn("Id");
                        esq.addColumn("Address", "Address");
                        esq.addColumn("AccountAddress.SxSubwayStation.Name", "MetroName");
                        esq.addColumn("AccountAddress.City.Name", "CityName");
                        esq.filters.add("VacancyCandidateFilter222", this.Terrasoft.createColumnFilterWithParameter(
                            this.Terrasoft.ComparisonType.EQUAL,
                            "Id", Id));
                        esq.getEntityCollection(function (response) {
                            if (response.success && response.collection.getCount() == 1) {
                                var entity = response.collection.getByIndex(0);
                                var addr = entity.get("Address");
                                var city = entity.get("CityName");
                                var metro = entity.get("MetroName");
                                var add = '';
                                if (city != undefined && city != 'Москва')
                                  add += city + ', ';
                                if (metro != undefined)
                                  add += metro + ', ';
                                if (addr != undefined)
                                  add += addr;
                                this.log('Add = ' + add);
                                this.set("BpMetroAutoFill", add);
                            }
                        }, this);
                }

В консоли хрома вижу что столбцы, кроме Address пишутся isNotFound. 

Делал согласно https://academy.terrasoft.ru/documents/technic-sdk/7-8/poluchenie-rezul…

EntitySchemaQuery умеет довыгребать AccountAddress.SxSubwayStation.Name в таблице AccountAddress есть столбец SxSubwayStationId

Аналогично с City.

Что не так делаю, подскажите плиз?

У меня такой же вопрос

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

Прооосто ужас.

...rootSchemaName: "AccountAddress"... //запрос уже идёт в AccountAddress
...esq.addColumn("City.Name", "CityName");... // поэтому писать AccountAddress.City.Name не правильно
...esq.addColumn("SxSubwayStation.Name", "MetroName");.. //аналогично
...esq.filters.add("VacancyCandidateFilter222", this.Terrasoft.createColumnFilterWithParameter(
this.Terrasoft.ComparisonType.EQUAL,
"Id", Id));
esq.getEntityCollection()... //Есть метод esq.getEntity(id, callback, scope). Зачем зазря писать фильр по id, а потом фильтровать коллекцию?

 

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

Угу, в первый день "отношений с платформой" этим "правильным методом" не получилось (был другой запрос), надо будет попробовать еще раз. Ща пока не до эстетики, но к ней придем, исправил, работает, уже хорошо, спасибо! 

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Есть sql-запрос вида:
select *
from Table T
where T.ProjectId = @ProjectId
    and not exists (select * from Table T1
                    where T1.ContactId = @ContactId
                        and T1.ParameterId = T.ParameterId)

Использование метода CreateFilterWithParameters() позволяет построить параметризированный запрос, но только exists:

var esqCardBlock = new EntitySchemaQuery(userConnection.EntitySchemaManager, "Table");
esqCardBlock.AddAllSchemaColumns();
var CardBlockFilters = esqCardBlock.Filters;                  CardBlockFilters.Add(esqCardBlock.CreateFilterWithParameters(FilterComparisonType.Equal,
                        "Project", projectId));                CardBlockFilters.Add(esqCardBlock.CreateFilterWithParameters(FilterComparisonType.Equal,
                        "[Table:Parameter:Parameter].Contact", contact));

Если же использовать CreateNotExistsFilter(), то не понятно, куда добавлять значение параметра @ContactId.

Какой всё-таки метод использовать для построения параметризированного запроса Not Exists?

У меня такой же вопрос

6 комментариев

Алла, возможно, такое получится при помощи выставления группе фильтров свойства .IsNot = true;

Как тут:

			var esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Activity");
			esq.AddAllSchemaColumns();
			esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Owner", currentUserId));
			esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Greater, "ModifiedOn", LastSyncDate));
			if (IsFirstSync) {
				esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Greater, "DueDate", Today));
			}
			esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal, "ShowInScheduler", true));
			var filtersByExisting = new EntitySchemaQueryFilterCollection(esq);
			filtersByExisting.IsNot = true;
			var notExFilter = esq.CreateFilterWithParameters(
				FilterComparisonType.IsNotNull,
				"[ActivityCorrespondence:Activity].SourceActivityId");
			filtersByExisting.Add(notExFilter);
			filtersByExisting.Add(esq.CreateFilterWithParameters(FilterComparisonType.Equal,
				"[ActivityCorrespondence:Activity].SourceAccount.Id", SourceAccountId));
			esq.Filters.Add(filtersByExisting);
			esq.Filters.Add(esq.CreateFilterWithParameters(FilterComparisonType.LessOrEqual, "CreatedOn", CurrentSyncDateTime));
			var entityCollection = esq.GetEntityCollection(UserConnection);

 

Саша,

спасибо за ответ. Я тоже уже думала так сделать, попробую и напишу о результате smiley

Саша,

таким способом, как ты предложил, получилось построить нужный фильтр.

Ещё вопрос: почему в документации на академии написано, что метод CreateFilterWithParameters перегруженный https://academy.terrasoft.ru/documents/technic-sdk/7-11/dobavlenie-vych…? Что имеется ввиду?

Алла, у меня по этой ссылке нет слов «перегруженный»  и «CreateFilterWithParameters».

Ошибка, речь идет об этой ссылке: https://academy.terrasoft.ru/documents/technic-sdk/7-11/ispolzovanie-en…

Войдите или зарегистрируйтесь, чтобы комментировать