Добрый вечер! Не знаю как такое возможно, чтобы ESQ.GetEntity() возвращал другую строку, при заданном первичном ключе в параметре функции. На скрине видно, что Id который задан и тот который вернул запрос совсем разные, а именно эта запись которую он взял идёт первой в таблице, что я не так делаю или в чём может ошибка? 

Прикрепленные файлы

Нравится

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

Здравствуйте.

Мне такую же ошибку не удалось воспроизвести - GetEntity отрабатывает правильно.

Попробуйте явно указать id, вот так: esq.GetEntity(UserConnection, new Guid("e76f59d2-c8ca-4bc1-80fd-0cdf02ab92dc"));

Ещё отловить бы запрос, который уходит в БД, возможно он некорректно формируется.

 

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

Здравствуйте. Задача была в валидации по полю и системной настройке. Читал статьи по фильтрам в ESQ и по форуму перелистал всё.

Всё работает, кроме одного момента.

 

Валидация:

Если значение выпадающего списка frequency равно "Ежедневно" и в выпадающем списке active поле = "Да" и количество записей в базе больше чем системной настройке(в данном случае 5) - срабатывает валидация на поле и всплывающее уведомление при попытке сохранения, или изменения записи.

 

frequency - выпадающий список периодичностей;

active - выпадающий список активности;

ermsg - сообщение ошибки;

maxCount - системная настройка (ранее "MaxAmountofDailyActivities");

response.collection.getCount() - актуальное кол-во записей;

 

При сохранении записи с полем "Ежедневно" + "Да", если таких записей уже 5  - валидация работает и правильно выдаёт ошибку. 

1.Но если любую другую запись, например с полем "Еженедельно" + "Да" изменить на "Ежедневно" + "Да", то ошибка не показывается и запись сохраняется. В данный момент записей становится уже 6.

2.Но если далее создавать записи с "Ежедневно" + "Да" или изменять другие на "Ежедневно" + "Да", ошибка показывается и всё продолжает работать нормально.

код метода прикрепил ниже + скриншоты 

 

methods: {
	asyncValidate: function(callback, scope) {
		this.callParent([function(response) {
			if (!this.validateResponse(response)) {
				return;
			}
			Terrasoft.chain(
				function(next) {
					this.validateSwimmingPrograms(function(response) {
						if (this.validateResponse(response)) {
							next();
						}
					}, this);
				},
				function(next) {
					callback.call(scope, response);
					next();
				}, this);
		}, this]);
	},
	validateSwimmingPrograms: function(callback, scope) {
		Terrasoft.SysSettings.querySysSettingsItem("MaxAmountofDailyActivities", function(maxCount) {
			var frequency = "";
			var active = "";
			var ermsg = this.get("Resources.Strings.ErrorMessage");
			var result = {success: true};
			if (this.get("UsrFrequency")) {
				frequency = this.get("UsrFrequency").displayValue;
			}
			if (this.get("UsrActive")) {
				active = this.get("UsrActive").displayValue;
			}
			var esq = Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "UsrSwimmingPrograms" });
			esq.addColumn("UsrFrequency.Name", "UsrFrequencyName");
			esq.addColumn("UsrActive.Name", "UsrActiveName");
			esq.filters.addItem(esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, 
				"UsrFrequency.Name", "Ежедневно"));
			esq.filters.addItem(esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
				"UsrActive.Name", "Да"));
			esq.getEntityCollection(function(response) {
				if (response.success && frequency === "Еженедельно" || frequency === "Ежемесячно" ||
					frequency === "Ежедневно" && active === "Нет"){
					result.success = true;
				}
				else if (response.success && frequency === "Ежедневно" && active === "Да" && (!this.isAddMode() && 
					response.collection.getCount() > maxCount) || (this.isAddMode() && 
					response.collection.getCount() >= maxCount)) {
						result.message = maxCount + ermsg + active;
						result.success = false;
				}
				callback.call(scope || this, result);
			}, this);
		}, this);
	}
},

Ниже по очереди: 

- Уже созданные 5 записей;

- при создании 6-ой с "Ежедневно" + "Да" выдаёт ошибку(выводит системную настройку(5), и в конце активность;

- При создании другой записи с другиме полями - ошибку не выводит(как и надо);

- При смене в пред. записи поля на "Ежедневно" - сохраняет (должно выводить ошибку);

- При последующих сохранения изменения записей всё работает корректно(где надо выдаёт ошибку, где не надо - не выдёт).

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

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

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

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

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

Нравится

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

То есть Ваша функция не вызывается при изменении существующей записи, а только для новых? Проверьте, выполняется ли вообще перед сохранением функция, добавленная в asyncValidate и доходит ли до вызова validateSwimmingPrograms. 

 

Правильные примеры валидации есть в этой теме  и в DocumentPageV2 пакета Document в «коробке»:

asyncValidate: function(callback, scope) {
	this.callParent([function(response) {
		if (!this.validateResponse(response)) {
			return;
		}
		Terrasoft.chain(
			function(next) {
				this.validateAccountOrContactFilling(function(response) {
					if (this.validateResponse(response)) {
						next();
					}
				}, this);
			},
			function(next) {
				this.validateUniqueNumber(function(response) {
					if (this.validateResponse(response)) {
						next();
					}
				}, this);
			},
			function(next) {
				callback.call(scope, response);
				next();
			}, this);
	}, this]);
},

 

Василий, попробуйте в браузере поставить отладчик и пошагово посмотреть, как выполняется эта функция. Заходит ли вообще в неё, правильно считает количество? Может, меняемая запись не учитывается, поскольку проверка идёт по последней ветке с «>=»?

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

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

Поставил отладчик, показывает только одно предупреждение при входе в карточку. 

В разделе Активности ничего не делал, не пойму почему ругается на это.

Названия справочных полей заменю на id полей, пока для вида оставил текст. 

Имею в виду, посмотреть, как по строкам выполняется скрипт, по каким ветвям условий выполняется в этом случае.

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

 Отработка скрипта при сохранении 5-ой записи с полями "Ежедневно" и "Да"

-Показывает, что перед добавлением было 4 записи: 

 

 

Далее, при попытке сохранить 6-ю записи с нужными полями, показывает что 5шт уже есть, то-есть пред. запись сохранилась и записалась:

 

 

Окей, работает, пробую изменить другую запись с рандомными полями на нужные.

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

 

 

Пробую еще раз добавить запись с нужными полями:

 

Попробуйте выполнить скрипт в отладке!

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

currentCount - кол-во существующих записей с нужными полями.

Тут показывает, что есть уже 5(при попытке создать 6-ю)

Тут исполнение функции происходит после изменения и сохранения другой записи с произвольными полями на нужные.

Ошибку не выкидывает, а просто сохраняет и уже currentCount = 6

 

Но когда уже есть 6, функция не позволяет дальше создавать с нужными полями или даже изменять произвольную запись на запись с "Ежедневно" / "Да". 

 

То есть Ваша функция не вызывается при изменении существующей записи, а только для новых? Проверьте, выполняется ли вообще перед сохранением функция, добавленная в asyncValidate и доходит ли до вызова validateSwimmingPrograms. 

 

Правильные примеры валидации есть в этой теме  и в DocumentPageV2 пакета Document в «коробке»:

asyncValidate: function(callback, scope) {
	this.callParent([function(response) {
		if (!this.validateResponse(response)) {
			return;
		}
		Terrasoft.chain(
			function(next) {
				this.validateAccountOrContactFilling(function(response) {
					if (this.validateResponse(response)) {
						next();
					}
				}, this);
			},
			function(next) {
				this.validateUniqueNumber(function(response) {
					if (this.validateResponse(response)) {
						next();
					}
				}, this);
			},
			function(next) {
				callback.call(scope, response);
				next();
			}, this);
	}, this]);
},

 

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

Спасибо огромное за наводку, разобрался.

Переделал что-бы функция реагировала на изменения: 

 

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

Добрый день коммьюнити,



Просто оставлю это здесь, чтобы самому потом не забыть как этим пользоваться)



Итак, у нас есть запрос с двумя where in или exists. В приведенном ниже примере он должен выбрать из перечня схем в SysSchema только те, UId которых есть в таблице SysModuleEntity в поле SysEntitySchemaUid и при этом сами значения SysModuleEntity должны быть в таблице SysModule и там признак IsSystem не должен быть false.



В переводе на русский: нам нужно отобрать только схемы, у которых есть пользовательские разделы, не являющиеся системными.

select * 
from sysschema 
where uid in (
    select sysentityschemauid from sysmoduleentity 
    where id in (
        select sysmoduleentityid from sysmodule
        where issystem = 'false'
    )
)
 
--он же, только через exists
select * 
from sysschema 
where exists (
    select id from sysmoduleentity 
    where sysentityschemauid = uid and exists(
        select id from sysmodule 
        where sysmoduleentityid = sysmoduleentity.id
        and issystem = 'false'
    )
)

Выполнить его нужно на клиентской части и по каким-то причинам нужно выполнить только через ESQ и лучше всего одним запросом. Например, мне это было нужно, чтобы вставить свой фильтр справочного поля в уже существующий экземпляр esq вместо того, чтобы городить тонны замещающей логики.

Чтобы это выполнить, нам нужно внимательно руководствоваться вот этой великолепной статьей https://community.terrasoft.ru/articles/kak-sdelat-filtraciu-pola-po-exists-filtru-s-parametrom-znacenie-drugogo-pola и проявить немного смекалочки) 

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

 

esq.filters.addItem(Terrasoft.createExistsFilter("[SysModule:SysModuleEntity:SysEntitySchemaUId:UId].Id")

а жаль, было бы удобно)



Вместо этого нам нужно сделать сразу несколько вложенных фильтров, вот так:

 

var subSubFilters = Terrasoft.createFilterGroup();
subSubFilters.addItem(Terrasoft.createColumnFilterWithParameter(
    Terrasoft.ComparisonType.EQUAL,
    "IsSystem", false));
var subFilters = Terrasoft.createFilterGroup();
subFilters.addItem(Terrasoft.createExistsFilter("[SysModule:SysModuleEntity].Id", subSubFilters));
esq.filters.addItem(Terrasoft.createExistsFilter("[SysModuleEntity:SysEntitySchemaUId:UId].Id", subFilters));

Фух, работа сделана, можно наградить себя чем-то вкусным и лучше всего очень вредным :)

Нравится

Поделиться

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

А почему бы вообще не вывернуть наизнанку, написав запрос к SysModule, связанным при помощи inner join с SysModuleEntity и затем с SysSchema?

select distinct sysschema.* from sysmodule 
inner join sysmoduleentity on sysmodule.sysmoduleentityid = sysmoduleentity.id
inner join sysschema on  sysmoduleentity.sysentityschemauid = sysschema.uid
where issystem  = 'false'

 

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

выглядит интересно, но как это написать с помощью фильтра в esq?)

Как добавляются join разных типов, см. тут. А distinct включается в конструкторе ESQ при помощи isDistinct: true (через запятую после значения rootSchemaName).

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

Доброго времени суток!Возникла необходимость учитывать регистр строки в фильтре при запросе esq С# . Никто не встречался с такой проблемой?Как это можно реализовать?

Нравится

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

Система полагается на стандартные настройки базы данных. В MS SQL по умолчанию регистр не учитывается, настройка меняется на уровне всей базы, как описано тут. Только учтите, что работу системы с изменёнными настройками регистрозависимости никто не тестировал и сайт может заработать некорректно в других местах.

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

Благодарю за ответ

Может кому пригодится. Решили эту проблему следующим образом - конвертировали строку в base64.

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

Добрый день, подскажите, как можно написать подобный запрос на 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, по таким же колонкам можно и накладывать фильтр.

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

Для отладки необходимо получить SQL текст ESQ запроса на front-end

Нравится

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

Насколько мне известно, такой возможности нет.

В случае с фронтендом можно смотреть запрос через SQL профайлер.

Насколько мне известно, такой возможности нет.

В случае с фронтендом можно смотреть запрос через SQL профайлер.

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

Добрый день!

Пробую реализовывать запрос к данных через ESQ таким образом:

var esq = Ext.create("Terrasoft.EntitySchemaQuery", {

                    rootSchemaName: "UsrTbl1"

                });

                esq.addColumn("Id");

                esq.addColumn("UsrPar1");esq.addColumn("UsrInfoId");

                esq.addColumn("UsrValueList.Name");//вот с такими строками уже начинается проблема

esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrValueList.Name", "значение1"));//и с такими фильтрами

 

Если нужно получить значение колонок с таблицы - rootSchemaName, то не вопрос.

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

GUID  видимо со String плохо понимают друг друга. Если ли примеры их нормального совместного использования в рамках ESQ?

Можно ли как-то понять причины неработоспособности прямых ссылок? Или хотя бы понять как с GUID быть? Даже если я значение GUID пытаюсь вставлять так, то не работает:

esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrInfoId", "337ED96B-B658-48B0-BBB6-7FACF918C735"));

Нравится

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

Eсли нужно получить справочную колонку, то её название нужно указывать без приставки "Id", как в схеме таблицы:

esq.addColumn("UsrInfo")

Аналогично и с фильтрами:

esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrInfo", "337ED96B-B658-48B0-BBB6-7FACF918C735"));

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

1. Через Id и тогда в качестве значения фильтра указываем Id:

var shipment = this.get("BTShipment");

sampleESQ.filters.addItem(sampleESQ.createColumnFilterWithParameter(

                    this.Terrasoft.ComparisonType.EQUAL, "[BTSampInShipment:BTSampleID].BTShipment.Id", shipment.value));

2. Через справочное поле и тогда в качестве значения указывать значение справочного поля:

var shipment = this.get("BTShipment");

sampleESQ.filters.addItem(sampleESQ.createColumnFilterWithParameter(

                    this.Terrasoft.ComparisonType.EQUAL, "[BTSampInShipment:BTSampleID].BTShipment", shipment));

А вообще, чтобы понять причину ошибки нужно отладиться на стороне клиента, если запрос уходит в базу данных, то посмотреть в SQL profiler, какой запрос идет в базу и какой результат работы этого запроса.

 

В js все Guid преобразуйте к нижнему регистру

те в вашем случае напишите что то типа esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrInfoId", "337ed.....

Eсли нужно получить справочную колонку, то её название нужно указывать без приставки "Id", как в схеме таблицы:

esq.addColumn("UsrInfo")

Аналогично и с фильтрами:

esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrInfo", "337ED96B-B658-48B0-BBB6-7FACF918C735"));

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

1. Через Id и тогда в качестве значения фильтра указываем Id:

var shipment = this.get("BTShipment");

sampleESQ.filters.addItem(sampleESQ.createColumnFilterWithParameter(

                    this.Terrasoft.ComparisonType.EQUAL, "[BTSampInShipment:BTSampleID].BTShipment.Id", shipment.value));

2. Через справочное поле и тогда в качестве значения указывать значение справочного поля:

var shipment = this.get("BTShipment");

sampleESQ.filters.addItem(sampleESQ.createColumnFilterWithParameter(

                    this.Terrasoft.ComparisonType.EQUAL, "[BTSampInShipment:BTSampleID].BTShipment", shipment));

А вообще, чтобы понять причину ошибки нужно отладиться на стороне клиента, если запрос уходит в базу данных, то посмотреть в SQL profiler, какой запрос идет в базу и какой результат работы этого запроса.

 

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

Пытаюсь не давать людям закрывать задачи по определенным условиям. Всё хорошо до момента, пока не надо сделать это из esq.

Точнее, функция this.callParent(arguments) никак не работает из

esq.getEntity(Id, function(result) {
    this.callParent(arguments);
}, this);

Уже пробовал сделать var self = this и вызывать от self, пробовал сохранить arguments до esq. Ничего не помогает, задача не сохраняется. 

esq надо делать обязательно, т.к. изменение в другом объекте, которое я проверяю, может сделать другой человек и мне нужно проверить это прямо перед сохранением.

Есть способ?

Нравится

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

Добрый день, нужно либо смотреть в сторону asyncValidate (пример есть в DocumentPageV2), либо переопределить Save.

save: function(config,flag) {
    if (flag) {
        this.callParent(arguments);
    } else {
        //Validation Block
        Terrasoft.chain(
            this.checkPhonesCount,
            function (callback, scope) {
                this.save(config||{}, true),
                    callback.call(scope || this);
            },
            this
        );
    }
 
},
/**
 * Проверка количества телефонов
 * */
checkPhonesCount: function (callback, scope) {
    var leadId = this.get("Id");
    var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
        rootSchemaName: "UsrLeadPhone"
    });
    esq.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, "Count");
 
    esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(
        Terrasoft.ComparisonType.EQUAL, "UsrLead", leadId));
    esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(
        Terrasoft.ComparisonType.NOT_EQUAL, "UsrPhone", ""));
    esq.filters.addItem(Terrasoft.createColumnIsNotNullFilter("UsrPhone"));
    esq.getEntityCollection(function (response) {
        if (response && response.success) {
            var collection = response.collection;
            if (collection && collection.getCount() > 0) {
                var count = collection.getByIndex(0).get("Count");
                if (count >= 1) {
                    callback.call(scope || this);
                    return;
                }
            }
            var msg = this.get("Resources.Strings.PhonesErrorMessage");
            msg = this.Ext.String.format(msg, 1);
            Terrasoft.showInformation(msg);
        }
    }, this);
},

 

Я делаю так: 

1) у кнопки сохранить bind меняю на другую функцию (пр. onBeforeSave)

2) в onBeforeSave реализую логику, а дальше вызываю/не вызываю save-метод

Также можно в save зашить проверку какого-либо параметра. Сохранять arguments, проверять параметр, если false-> вызывать свою функцию, в конце своей функции параметр = true и вызвать save с  сохр. аргументами. Тоже в принципе вариант

Добрый день, нужно либо смотреть в сторону asyncValidate (пример есть в DocumentPageV2), либо переопределить Save.

save: function(config,flag) {
    if (flag) {
        this.callParent(arguments);
    } else {
        //Validation Block
        Terrasoft.chain(
            this.checkPhonesCount,
            function (callback, scope) {
                this.save(config||{}, true),
                    callback.call(scope || this);
            },
            this
        );
    }
 
},
/**
 * Проверка количества телефонов
 * */
checkPhonesCount: function (callback, scope) {
    var leadId = this.get("Id");
    var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
        rootSchemaName: "UsrLeadPhone"
    });
    esq.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, "Count");
 
    esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(
        Terrasoft.ComparisonType.EQUAL, "UsrLead", leadId));
    esq.filters.addItem(Terrasoft.createColumnFilterWithParameter(
        Terrasoft.ComparisonType.NOT_EQUAL, "UsrPhone", ""));
    esq.filters.addItem(Terrasoft.createColumnIsNotNullFilter("UsrPhone"));
    esq.getEntityCollection(function (response) {
        if (response && response.success) {
            var collection = response.collection;
            if (collection && collection.getCount() > 0) {
                var count = collection.getByIndex(0).get("Count");
                if (count >= 1) {
                    callback.call(scope || this);
                    return;
                }
            }
            var msg = this.get("Resources.Strings.PhonesErrorMessage");
            msg = this.Ext.String.format(msg, 1);
            Terrasoft.showInformation(msg);
        }
    }, this);
},

 

Еще можно создать валидатор, который будет делать все проверки и срабатывать перед сохранением записи, его например привязать к полю "состояние"

Вообще, лучше не делать такие проверки только лишь в клиентской логике. Чисто теоретически, пользователь сможет отловить выполнение функции и в отладчике перешагнуть проверку. Хорошо бы и на объекте в обработчике Saving проверять соблюдение условия.

1. Если не вчитываться в смысл задачи, а только подсказать как сделать желаемое то вот этот способ:

save: function() {
   ...
   var args = arguments;
   var parentMethod = this.getParentMethod();
   ....
   esq.GetEntity(function() {
       parentMethod.apply(this, args)
   }, this);
}

2. По смыслу же задачи, вам нужно делать валидацию, а не переопределять методы сохранения. посмотрите примеры в коде с использованием методов addColumnValidator, validate, asyncValidate. 

addColumnValidator, validate делают синхронные проверки. asyncValidate асинхронная валидация, используется когда нужно сделать например запрос в БД для проверки.

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

Здравствуйте. Интересует способ использования "Group By"  в entitySchemaQuery (сервер). При поиске наткнулся на топик - https://community.terrasoft.ru/questions/gruppirovka-v-entityschemaquery , но увы, ссылка с ответом битая. 

Нравится

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

Пример использования на C#, документацию нашел только для клиентских запросов, но по аналогии все понятно

var query = new EntitySchemaQuery(_userConnection.EntitySchemaManager, schemaName);
var columnCount = query.AddColumn(query.CreateAggregationFunction(AggregationTypeStrict.Count, query.PrimaryQueryColumn.Name));
var countEntity = query.GetEntityCollection(UserConnection)[0];
var count = countEntity.GetTypedColumnValue<int>(comnCount.Name);
return count;

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

var esq = new Order(UserConnection);
esq.AddColumn(esq.CreateAggregationFunction(AggregationTypeStrict.Count, "Customer.Name").All());
	esq.AddColumn("Description");
	esq.AddColumn("Name");
	esq.AddColumn("Customer");

Добавит в запрос 

GROUP BY Order.Description, Document.Name, Order.CustomerId, Customer.Name;

 

 

 

 

 

Пример использования на C#, документацию нашел только для клиентских запросов, но по аналогии все понятно

var query = new EntitySchemaQuery(_userConnection.EntitySchemaManager, schemaName);
var columnCount = query.AddColumn(query.CreateAggregationFunction(AggregationTypeStrict.Count, query.PrimaryQueryColumn.Name));
var countEntity = query.GetEntityCollection(UserConnection)[0];
var count = countEntity.GetTypedColumnValue<int>(comnCount.Name);
return count;

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

var esq = new Order(UserConnection);
esq.AddColumn(esq.CreateAggregationFunction(AggregationTypeStrict.Count, "Customer.Name").All());
	esq.AddColumn("Description");
	esq.AddColumn("Name");
	esq.AddColumn("Customer");

Добавит в запрос 

GROUP BY Order.Description, Document.Name, Order.CustomerId, Customer.Name;

 

 

 

 

 

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

Спасибо большое!

Вот, на всякий случай, и пример серверного кода:

EntitySchema entitySchema = UserConnection.EntitySchemaManager.GetInstanceByName("SysProcessElement");
var query = new EntitySchemaQuery(entitySchema);
EntitySchemaQueryColumn elementUIdColumn = query.AddColumn("SchemaElementUId");
EntitySchemaQueryColumn executeCountColumn = query.AddColumn(query.CreateAggregationFunction(AggregationTypeStrict.Count,
	entitySchema.PrimaryColumn.Name));
 
EntityCollection entities = query.GetEntityCollection(UserConnection);

 

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

Я для серверного кода пример и приводил :) От клиентского только документация :)

Вот документация по серверной. Ещё в этом документе есть информация.

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

Добрый день,подскажите пожалуйста,а в мобильном приложении есть функция автозаполнения поля ? Если да,то как это можно организовать ? Чтобы при создании новой записи в разделе,поле автоматически заполнялось значением,что то вроде счетчика записей. Например у меня в разделе есть 10 записей - запись 1,запись 2,запись 3 ... 10. При создании новой чтобы поле Название сразу заполнялось как запись 11. Подскажите примерный ход действий(на данный момент беру запросом с базы,сортируя и беру следующее число,но такой подход не очень хороший). Может быть есть более правильный вариант ? Спасибо!

Нравится

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

Автонумерацию таким образом делать не нужно. Во-первых, для этого есть стандартный механизм в системе. Во-вторых, в мобильном приложении это может вызвать проблемы с совпадением номеров при синхронизации записей. Автонумерацию нужно на стороне BPM делать.

Что касается автоматической установки значений, то есть несколько вариантов. Можно сделать, например, на уровне событий объекта мобильного приложения:

Terrasoft.sdk.Model.setModelEventHandler("ActivitySKU", 
    Terrasoft.ModelEvents[Terrasoft.ModelEventKinds.Before].update,
    function(config) {
        var record = config.scope.eventConfig.records[0];
        record.set("UsrIsChecked", true);
        Ext.callback(config.success, config.scope);
});

Или с помощью Custom бизнес правила:

Terrasoft.sdk.Model.addBusinessRule("ModelName", {
    name: "RuleName",
    ruleType: Terrasoft.RuleTypes.Custom,
    events: [Terrasoft.BusinessRuleEvents.Load, Terrasoft.BusinessRuleEvents.ValueChanged],
    executeFn: function(record, rule, column, customData, callbackConfig) {
        record.set("UsrColumn", "some value");
        Ext.callback(callbackConfig.success, callbackConfig.scope);
    }
})

Третий вариант - в кастомной странице повесить на загруженную запись дополнительный обработчик на изменение записи:

onLoadRecord: function(loadedRecord) {
    this.callParent(arguments);
    loadedRecord.on("columnchanged", this.onRecordColumnChanged, this);
},

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

var control = Ext.getCmp("control_id");
control.setValue("some value");

 

Такое есть смысл на стороне сервера. Есть специальное действие в БП для получения номера по порядку.

На мобильном в автономном режиме такая нумерация не имеет смысла, поскольку на сервере или на другом телефоне могут также добавить записи. Поле можно оставить пустым, а заполнить тем же БП при синхронизации в основную базу.

Автонумерацию таким образом делать не нужно. Во-первых, для этого есть стандартный механизм в системе. Во-вторых, в мобильном приложении это может вызвать проблемы с совпадением номеров при синхронизации записей. Автонумерацию нужно на стороне BPM делать.

Что касается автоматической установки значений, то есть несколько вариантов. Можно сделать, например, на уровне событий объекта мобильного приложения:

Terrasoft.sdk.Model.setModelEventHandler("ActivitySKU", 
    Terrasoft.ModelEvents[Terrasoft.ModelEventKinds.Before].update,
    function(config) {
        var record = config.scope.eventConfig.records[0];
        record.set("UsrIsChecked", true);
        Ext.callback(config.success, config.scope);
});

Или с помощью Custom бизнес правила:

Terrasoft.sdk.Model.addBusinessRule("ModelName", {
    name: "RuleName",
    ruleType: Terrasoft.RuleTypes.Custom,
    events: [Terrasoft.BusinessRuleEvents.Load, Terrasoft.BusinessRuleEvents.ValueChanged],
    executeFn: function(record, rule, column, customData, callbackConfig) {
        record.set("UsrColumn", "some value");
        Ext.callback(callbackConfig.success, callbackConfig.scope);
    }
})

Третий вариант - в кастомной странице повесить на загруженную запись дополнительный обработчик на изменение записи:

onLoadRecord: function(loadedRecord) {
    this.callParent(arguments);
    loadedRecord.on("columnchanged", this.onRecordColumnChanged, this);
},

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

var control = Ext.getCmp("control_id");
control.setValue("some value");

 

Спасибо!

 

Бершеда Д. Н. пишет:

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

 Здравствуйте.

 

Данная проблема, скорее всего, решается передачей в метод .set третьего параметра true.

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