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

Нравится

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

Кирилл, для решения задачи используйте элемент [Карточка редактирования] с установленной опцией "Редактировать существующую запись" (в поле "Идентификатор записи" нужно указать параметр, содержащий ID созданной статьи).

Спасибо!

Еще вопрос.
У меня есть активность-задача на основании запроса на обслуживания. Мне нужно сделать БП, который бы при получении сигнала о закрытии запроса на обслуживания, закрывал это зависимую активность-задачу.
Сигнал сделал, данные с запроса прочитал. А дальше не понимаю, что делать. По идее дальше должен идти блок изменения данных объкта Активность. Но как связать этот блок с теми данными, которые я прочитал из запроса?
Спасибо.

Кирилл, далее используйте действие [Изменение данных]. Чтобы изменить нужные активности, укажите условия фильтрации:

/system/files/14-11-2013_13-21-22.png

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

Добрый день.

Подскажите пожалуйста, как ограничить минимальное количество записей в реестре?
Т.е. как сделать чтобы пользователь не смог удалить все записи? Должна остатся как минимум одна запись. И кнопка "Удалить" должна стать не активной.

В принципе достаточно события которое происходит при любом обновлении реестра. И на него повесить чтото типа :

if (Page.DataSource.Rows.Count > 1)
{
  Page.DeleteButton.SetEnabled(true);
}
else
{
  Page.DeleteButton.SetEnabled(false);
}

Нравится

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

Для того, чтобы изменить количество выводимых строк, следует в обработчике события PageLoadComplete добавить следующую строку:

Page.DataSource.PageRowsCount = 20;

где 20 – количество записей, которые следует загружать.

Изменения следует вносить в тот реестр, где нам нужно больше(меньше) строк, либо в базовый реестр, от которого мы наследуем все остальные (если нужно для всех реестров).

Мне кажется, автор спрашивал о другом...

Возможно, стоит повесить эту логику на события датасорса в окне реестра: "После сохранения записи", "После удаления записи" и "После загрузки данных" (для учёта первого открытия и смены записи в основном реестре, если это деталь). Но не уверен, достаточно ли их.

Дмитрий, мне надо запретить пользователю удалять запись если она последняя, а не общее количестов выводимых строк в реестре.
Александр, так и делаю, хотелось более аакуратного решения, например событие Refresh у грида, но найти такое событие не получилось.
Возникло две проблемы:
1. если подписатся на событие "DataSourceBeforeRemove" то оно не срабатывает перед удалением.
2. если я из кода устанавливаю

Page.DeleteButton.SetEnabled(false);

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

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

А с событиями проблема.
При удалении работает только "DataSourceRemoved", а при добавлении не работает ни одно событие, вот список : "DataSourceBeforeInsert, DataSourceInserted, DataSourceBeforeSave, DataSourceSaved".
Точнее при добавлении записи срабатывает "DataSourceLoaded", но при срабатывании

Page.DataSource.Rows.Count

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

Page.DeleteButton.SetEnabled(true/false)

Илья, после любой операции, будь то добавление, удаление, изменение записи - происходит обновление DataSouce'а, соответственно в общем случае всегда будет выполнятся одно событие:

DataSourceLoadRowsResponseRegistered

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

var dataSourceRowsCount = Page.DataSource.Rows.Count;
if(dataSourceRowsCount < 2)
{
Page.DeleteButton.SetEnabled(false)
}

Дмитрий, спасибо, событие действительно происходит, но при добавлении записи Page.DataSource.Rows.Count всегда равен 1.
Как можно посмотреть реальное количество записей не выполняя SELECT к базе?

Илья, только при добавлении?

Дмитрий, также при удалении равен 0. А при обновлении реестра показывает реальное количество записей.

Илья, попробуйте, пожалуйста, рефрешнуть грид, а также вызвать LoadRows() для DataSource'а перед тем как считывать кол-во записей:

Page.DataSource.LoadRows();
TreeGrid.RefreshData();
var dataSourceRowsCount = Page.DataSource.Rows.Count;
if(dataSourceRowsCount < 2)
{
Page.DeleteButton.SetEnabled(false)
}

(где TreeGrid - это контрол для DataSource'a)

Дмитрий, если я в событии DataSourceLoadRowsResponseRegistered сделаю рефреш грида, то образуется рекурсия.

Проверил, вот так работает:

var dataSourceRowsCount = Page.DataSource.Rows.Count;
if(dataSourceRowsCount == 1)
{
	Page.DataSource.LoadRows();
	Page.TreeGrid.RefreshData();
}
dataSourceRowsCount = Page.DataSource.Rows.Count;
if(dataSourceRowsCount < 2)
{
	Page.DeleteButton.SetEnabled(false);
}

Вот мой код:

var dataSourceRowsCount = Page.DataSource.Rows.Count;
MessagePanel messagePanel = ControlUtilities.FindControl(
                Page.AspPage.Controls[0], "BaseMessagePanel", true) as MessagePanel;
if (messagePanel != null) {
                messagePanel.AddMessage(Warning, dataSourceRowsCount.ToString(), MessageType.Warning);
}
if(dataSourceRowsCount == 1)
{
	Page.DataSource.LoadRows();
	Page.TreeGrid.RefreshData();
}
dataSourceRowsCount = Page.DataSource.Rows.Count;
if (messagePanel != null) {
                messagePanel.AddMessage(Warning, dataSourceRowsCount.ToString(), MessageType.Warning);
}
if(dataSourceRowsCount < 2)
{
	//Page.DeleteButton.SetEnabled(false);
}
return true;

Вот результат при добавлении:

Дмитрий, а на какое событие Вы вешали обработчик? Делаю как и у Вас но получаю зацикливание и BPM падает.

Падение происходит когда строки

//        Page.DataSource.LoadRows();
//        Page.TreeGrid.RefreshData();

раскоментированы

Илья, так у Вас первые две строки

// Page.DataSource.LoadRows();
// Page.TreeGrid.RefreshData();

выполняются всегда, если их раскоментировать. Нужно их убрать и поместить в if.
Если так сделаете - то зацикливание произойдет только тогда, когда Вы добавляете первую запись в реестр (до этого было 0). Можно добавить какой-то int параметр i = 0 в процесс, и в условие добавить

if(dataSourceRowsCount == 1 && i == 0) {
i++;
LoadRows();
Refresh();
}

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

хочу сделать страницу для ввода значений параметров БП , как далее значения введённые на странице присвоить параметрам БП. Была следующая мысль:в странице создать параметры, которым присваивать значения контролов. А затем в БП обращаться к свойству PageParameters того UserTask'а, который открывает страницу или надо как-то по-другому?

Нравится

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

Здравствуйте, Ольга!
Ваш вариант возможен. Но если пользователь не введет параметры и закроет страницу, логика процесса, скорее всего нарушится.
Можно добавить соответствующие поля в объект (например, Активность) и страницу его редактирования. По умолчанию их можно скрывать и показывать в ходе процесса. Далее, когда пользователь введет нужные данные, в процессе их можно будет получить напрямую из объекта.

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

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

Есть у меня BPMonline OnSite. Рядом есть веб-сайт на Joomla!. В BPM есть каталог продуктов для сайта. В Joomla! он тянется динамически php'ой через pdo sql.

Вопрос: есть на сайте поиск......человек вводит какое то словесо.....ээээ......как мне его искать в
ms sql'е....или гугл спасет меня.......в общем короче не понимаю я.

Буду рад любым конструктивным мыслям, направлениям, пинкам в нужную сторону :wink:

P.S. СЛОВО ODATA В ЭТОМ ПОСТЕ НЕ ВСПОМИНАТЬ!!!! НЕ РАБОТАЕТ ОНО С PHP!!!! УЖЕ ПИСАЛ!!! И ВООБЩЕ ВОПРОС НЕ ОБ ЭТОМ!!!

Нравится

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

Александр, а куда тянется список продуктов в Joomla сайте? Вот там, по идее, и надо искать, зачем в ms sql? Ведь, насколько я понимаю, продукты в ms sql = продукты pdo sql.

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

Есть такой код:

esqDocResult = new EntitySchemaQuery(esqManager, "Document");
IdColumn = esqDocResult.AddColumn("Id");
CurAppRouteIdColumn = esqDocResult.AddColumn("ApprovalRoute.Id");
CurAppNodeIdColumn = esqDocResult.AddColumn("CurrentApprovalNode.Id");

Entity parentDoc = esqDocResult.GetEntity(UserConnection, parentDocId);
parentDoc.SetColumnValue (CurAppNodeIdColumn.Name, nextNodeId);
parentDoc.Save();

На parentDoc.SetColumnValue ругается, что не найдено значение "имя столбца", причем как не пиши: как сейчас в коде написано, или так"CurrentApprovalNode.Id" или так "CurrentApprovalNodeId"....

Так вообще можно сделать то?

Нравится

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

Только сейчас обратил внимание: оно постоянно ругается не на мой столбец, а
"Значение с именем CurrencyRate не найдено".
Ничего не понял.......
При чем здесь вообще курс валюты?

Предполагаю, что в БП объекта "Документ" есть логика, завязанная на колонку "CurrencyRate". При попытке открыть объект оно не может к ней обратиться и валится. Нужно сделать AddColumn и этой колонки тоже.

Сделал проще через Update

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

Как сделать фильтрацию или в следующим примере:

использовал

{"logicalOperation", LogicalOperationStrict.Or}
не работает

filters.Add(new Dictionarystring, object> {
                                       {"comparisonType", FilterComparisonType.IsNotNull},
                                       {"leftExpressionColumnPath", "Debt.Id"},
                                       {"useDisplayValue", false},
                                                                   {"rightExpressionParameterValues", new object[] {Guid.Empty}}
                                                                   
                                                                }
                                                        );
                                filters.Add(new Dictionarystring, object> {
                                       {"comparisonType", FilterComparisonType.IsNotNull},
                                       {"leftExpressionColumnPath", "ReceivDebt.Id"},
                                       {"useDisplayValue", false},
                                                                   {"rightExpressionParameterValues", new object[] {Guid.Empty}}
                                                                 
                                                                }
                                                        );

Нравится

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

Здравствуйте, Баглан!
А работает, если применять только один фильтр?

"Андрей Каспаревич" написал:filters.Add(new Dictionary {
                                       {"comparisonType", FilterComparisonType.IsNotNull},
                                       {"leftExpressionColumnPath", "Debt.Id"},
                                       {"useDisplayValue", false},
                                                                   {"rightExpressionParameterValues", new object[] {Guid.Empty}}
                                                                   
                                                                }
                                                        );

Если применять 1 фильтр работает
к примеру этот:
filters.Add(new Dictionary {
{"comparisonType", FilterComparisonType.IsNotNull},
{"leftExpressionColumnPath", "Debt.Id"},
{"useDisplayValue", false},
{"rightExpressionParameterValues", new object[] {Guid.Empty}}

}
);

Баглан, приведите, пожалуйста, полный код скрипта.
В частности, интересует инициализация filters. Должно быть что-то вроде:

filters = structure.CreateFiltersGroup("CustomFilters", LogicalOperationStrict.Or);

"Андрей Каспаревич" написал:

Баглан, приведите, пожалуйста, полный код скрипта.

В частности, интересует инициализация filters. Должно быть что-то вроде:

filters = structure.CreateFiltersGroup("CustomFilters", LogicalOperationStrict.Or);

С уважением,

Каспаревич Андрей

Эксперт 3-й линии поддержки

Андрей добрый день, высылаю полный текст скрипта на C#

Page.CallFromQueueEdit.PrepareLookupFilter += delegate (object sender, LookupEditEventArgs e) {
                Collection<Dictionary<string, object>> filters = e.Filters;
                filters.Add(new Dictionary<string, object> { 
	                               {"comparisonType", FilterComparisonType.Equal}, 
	                               {"leftExpressionColumnPath", "Type.Id"},
	                               {"useDisplayValue", false}, 
	                               {"rightExpressionParameterValues", new object[] {activityTypeId}}
								}
							); 
                filters.Add(new Dictionary<string, object> { 
	                               {"comparisonType", FilterComparisonType.LessOrEqual}, 
	                               {"leftExpressionColumnPath", "StartDate"},
	                               {"useDisplayValue", false}, 
	                               {"rightExpressionParameterValues", new object[] {UserConnection.CurrentUser.GetCurrentDateTime()}}
								}
							); 							
                filters.Add(new Dictionary<string, object> { 
	                               {"comparisonType", FilterComparisonType.Equal}, 
	                               {"leftExpressionColumnPath", "Status.Id"},
	                               {"useDisplayValue", false}, 
	                               {"rightExpressionParameterValues", new object[] {NotStartedStatusId, InWorkStatusId}}
								}
							); 	
                filters.Add(new Dictionary<string, object> { 
	                               {"comparisonType", FilterComparisonType.IsNotNull}, 
	                               {"leftExpressionColumnPath", "Debt.Id"},
	                               {"useDisplayValue", false},
								   {"rightExpressionParameterValues", new object[] {Guid.Empty}},
								   {"logicalOperation", LogicalOperationStrict.Or}
								}
							);
				/*
				filters.Add(new Dictionary<string, object> { 
	                               {"comparisonType", FilterComparisonType.IsNotNull}, 
	                               {"leftExpressionColumnPath", "ReceivDebt.Id"},
	                               {"useDisplayValue", false},
								   {"rightExpressionParameterValues", new object[] {Guid.Empty}},
								   {"logicalOperation", LogicalOperationStrict.Or}
								}
							); */
};

Баглан, судя по коду, проблема в том, что фильтры добавляются по одному, а не блоком. То есть Вам нужно сформировать блок фильтров с логическим оператором и уже его добавлять в e.Filters.
Попробуйте так:

Page.CallFromQueueEdit.PrepareLookupFilter += delegate (object sender, LookupEditEventArgs e) {
                var filters = structure.CreateFiltersGroup("CustomFilters", LogicalOperationStrict.Or); 
                filters.Add( structure.CreateFilterWithParameters( dataSource.Schema, 
                FilterComparisonType.Equal, "Type.Id", activityTypeId)); 
                filters.Add( structure.CreateFilterWithParameters(dataSource.Schema, 
                FilterComparisonType.LessOrEqual, "StartDate",   UserConnection.CurrentUser.GetCurrentDateTime());                                                      
               //....
                e.Filters.Add(filters);

"Андрей Каспаревич" написал:{"comparisonType", FilterComparisonType.IsNotNull},

Ругаеться на это e.Filters.Add(structure); тип не верный не верно передаем параметр structure, должно быть таким образом: Collection>

DataSource dataSource = Page.ActivityDataSource;
				var structure = dataSource.CurrentStructure;
				var filterGroupName = "CustomFilters";
				//remove existing filters
                var filters = dataSource.FindFiltersGroupByName(filterGroupName);
                if (filters != null) {
	                structure.Filters.Remove(filters);
                }
                filters = structure.CreateFiltersGroup(filterGroupName, LogicalOperationStrict.And); 
                filters.Add(structure.CreateFilterWithParameters(dataSource.Schema, FilterComparisonType.Equal, "Type.Id", activityTypeId)); 
                filters.Add(structure.CreateFilterWithParameters(dataSource.Schema, FilterComparisonType.LessOrEqual, "StartDate",   UserConnection.CurrentUser.GetCurrentDateTime()));   
 
				var statusFilters = new DataSourceFilterCollection() {
	                LogicalOperation = LogicalOperationStrict.Or,
                };
				statusFilters.Add(dataSource.CreateFilterWithParameters(FilterComparisonType.Equal, "Status.Id", NotStartedStatusId));
				statusFilters.Add(dataSource.CreateFilterWithParameters(FilterComparisonType.Equal, "Status.Id", InWorkStatusId));
				filters.Add(statusFilters);
 
				var debtFilters = new DataSourceFilterCollection() {
	                LogicalOperation = LogicalOperationStrict.Or,
                };
				debtFilters.Add(dataSource.CreateFilterWithParameters(FilterComparisonType.IsNotNull, "Debt.Id"));
				debtFilters.Add(dataSource.CreateFilterWithParameters(FilterComparisonType.IsNotNull, "ReceivDebt.Id"));
				filters.Add(debtFilters);
				structure.Filters.Add(filters);
				e.Filters.Add(structure);

Здравствуйте, Баглан!
Уточнил информацию у разработчиков.
Особенность фильтрации на PrepareLookupFilter состоит в том, что либо всё фильтруется через оператор “AND” (по умолчанию) либо через оператор “OR” (Логика устанавливается при помощи параметра)

e.ParametersValue.Add("logicalOperation", LogicalOperationStrict.Or);

Так как в примере идет пересечение AND и OR логики фильтрации, то остается более сложный путь:
1) Написать запрос, с помощью которого отберутся только те Id, которые удовлетворяют условию фильтрации;
2) В фильтрации PrepareLookupFilter фильтровать по найденным Id.
Пример реализации второго варианта:

List<object> offeringList = new List<object>();
var offeringSelect = new Select(UserConnection).
                Column("o", "Id").
                From("Offering").As("o").
                InnerJoin("OfferingType").As("ot").
                On("o", "TypeId").IsEqual("ot", "Id"). 
                InnerJoin("Service").As("s").
                On("o", "ServiceId").IsEqual("s", "Id"). 
                InnerJoin("TypeOfService").As("tos").
                On("s", "TypeOfServiceId").IsEqual("tos", "Id").
                Where("ot", "IsService").IsEqual(Column.Parameter(true)).
                And("tos", "Id").IsEqual(Column.Parameter(BusinessServiceTypeId)).              
                And().OpenBlock
                               ("s", "TypeOfServiceRequestId").IsEqual(Column.Parameter(ServiceCallTypeUId)).
                               Or("o", "ServiceId").IsNull().
                               Or().OpenBlock
                                               ("s", "TypeOfServiceRequestId").IsEqual(Column.Parameter(IncidentTypeUId)).
                                               And().Exists(
                                                               new Select(UserConnection).Column("tech", "Id").From("Service").As("tech").
                                                               Where("tech", "ServiceParentId").IsEqual("s", "Id").
                                                               And("tech", "TypeOfServiceId").IsEqual(Column.Parameter(TechServiceTypeId)).
                                                               And("tech", "TypeOfServiceRequestId").IsEqual(Column.Parameter(ServiceCallTypeUId))
                                               ).
                               CloseBlock().
                CloseBlock() as Select;
 
using (var dbExecutor = UserConnection.EnsureDBConnection()) {
                using (var dr = offeringSelect.ExecuteReader(dbExecutor)) {
                               while (dr.Read()) {
                                               offeringList.Add((object)UserConnection.DBTypeConverter.DBValueToGuid(dr[0]));
                               }
                }
}
 
if (offeringList.Count == 0) {
                offeringList.Add((object)Guid.Empty);
}
 
 
 
e.Filters.Clear();
var filter = new Dictionary<string, object> { 
                               { "comparisonType", FilterComparisonType.Equal }, 
                               { "leftExpressionColumnPath", "Id" },
                               { "useDisplayValue", false }, 
                               { "rightExpressionParameterValues", offeringList.ToArray()}};
e.Filters.Add(filter);

"Андрей Каспаревич" написал:

Здравствуйте, Баглан!

Уточнил информацию у разработчиков.

Особенность фильтрации на PrepareLookupFilter состоит в том, что либо всё фильтруется через оператор “AND” (по умолчанию) либо через оператор “OR” (Логика устанавливается при помощи параметра)

e.ParametersValue.Add("logicalOperation", LogicalOperationStrict.Or);

Так как в примере идет пересечение AND и OR логики фильтрации, то остается более сложный путь:

1) Написать запрос, с помощью которого отберутся только те Id, которые удовлетворяют условию фильтрации;

2) В фильтрации PrepareLookupFilter фильтровать по найденным Id.

Пример реализации второго варианта:

List<object> offeringList = new List<object>();

var offeringSelect = new Select(UserConnection).

                Column("o", "Id").

                From("Offering").As("o").

                InnerJoin("OfferingType").As("ot").

                On("o", "TypeId").IsEqual("ot", "Id").

                InnerJoin("Service").As("s").

                On("o", "ServiceId").IsEqual("s", "Id").

                InnerJoin("TypeOfService").As("tos").

                On("s", "TypeOfServiceId").IsEqual("tos", "Id").

                Where("ot", "IsService").IsEqual(Column.Parameter(true)).

                And("tos", "Id").IsEqual(Column.Parameter(BusinessServiceTypeId)).              

                And().OpenBlock

                               ("s", "TypeOfServiceRequestId").IsEqual(Column.Parameter(ServiceCallTypeUId)).

                               Or("o", "ServiceId").IsNull().

                               Or().OpenBlock

                                               ("s", "TypeOfServiceRequestId").IsEqual(Column.Parameter(IncidentTypeUId)).

                                               And().Exists(

                                                               new Select(UserConnection).Column("tech", "Id").From("Service").As("tech").

                                                               Where("tech", "ServiceParentId").IsEqual("s", "Id").

                                                               And("tech", "TypeOfServiceId").IsEqual(Column.Parameter(TechServiceTypeId)).

                                                               And("tech", "TypeOfServiceRequestId").IsEqual(Column.Parameter(ServiceCallTypeUId))

                                               ).

                               CloseBlock().

                CloseBlock() as Select;

 

using (var dbExecutor = UserConnection.EnsureDBConnection()) {

                using (var dr = offeringSelect.ExecuteReader(dbExecutor)) {

                               while (dr.Read()) {

                                               offeringList.Add((object)UserConnection.DBTypeConverter.DBValueToGuid(dr[0]));

                               }

                }

}



if (offeringList.Count == 0) {

                offeringList.Add((object)Guid.Empty);

}







e.Filters.Clear();

var filter = new Dictionary<string, object> {

                               { "comparisonType", FilterComparisonType.Equal },

                               { "leftExpressionColumnPath", "Id" },

                               { "useDisplayValue", false },

                               { "rightExpressionParameterValues", offeringList.ToArray()}};

e.Filters.Add(filter);

С уважением,

Каспаревич Андрей

Эксперт 3-й линии поддержки


Спасибо у меня получилось сделать.

"Бахгельдиев Баглан Абылаевич" написал:
Андрей Каспаревич пишет:

Здравствуйте, Баглан!

Уточнил информацию у разработчиков.

Особенность фильтрации на PrepareLookupFilter состоит в том, что либо всё фильтруется через оператор “AND” (по умолчанию) либо через оператор “OR” (Логика устанавливается при помощи параметра)

e.ParametersValue.Add("logicalOperation", LogicalOperationStrict.Or);

Так как в примере идет пересечение AND и OR логики фильтрации, то остается более сложный путь:

1) Написать запрос, с помощью которого отберутся только те Id, которые удовлетворяют условию фильтрации;

2) В фильтрации PrepareLookupFilter фильтровать по найденным Id.

Пример реализации второго варианта:

List<object> offeringList = new List<object>();

var offeringSelect = new Select(UserConnection).

                Column("o", "Id").

                From("Offering").As("o").

                InnerJoin("OfferingType").As("ot").

                On("o", "TypeId").IsEqual("ot", "Id").

                InnerJoin("Service").As("s").

                On("o", "ServiceId").IsEqual("s", "Id").

                InnerJoin("TypeOfService").As("tos").

                On("s", "TypeOfServiceId").IsEqual("tos", "Id").

                Where("ot", "IsService").IsEqual(Column.Parameter(true)).

                And("tos", "Id").IsEqual(Column.Parameter(BusinessServiceTypeId)).              

                And().OpenBlock

                               ("s", "TypeOfServiceRequestId").IsEqual(Column.Parameter(ServiceCallTypeUId)).

                               Or("o", "ServiceId").IsNull().

                               Or().OpenBlock

                                               ("s", "TypeOfServiceRequestId").IsEqual(Column.Parameter(IncidentTypeUId)).

                                               And().Exists(

                                                               new Select(UserConnection).Column("tech", "Id").From("Service").As("tech").

                                                               Where("tech", "ServiceParentId").IsEqual("s", "Id").

                                                               And("tech", "TypeOfServiceId").IsEqual(Column.Parameter(TechServiceTypeId)).

                                                               And("tech", "TypeOfServiceRequestId").IsEqual(Column.Parameter(ServiceCallTypeUId))

                                               ).

                               CloseBlock().

                CloseBlock() as Select;

 

using (var dbExecutor = UserConnection.EnsureDBConnection()) {

                using (var dr = offeringSelect.ExecuteReader(dbExecutor)) {

                               while (dr.Read()) {

                                               offeringList.Add((object)UserConnection.DBTypeConverter.DBValueToGuid(dr[0]));

                               }

                }

}

if (offeringList.Count == 0) {

                offeringList.Add((object)Guid.Empty);

}

e.Filters.Clear();

var filter = new Dictionary<string, object> {

                               { "comparisonType", FilterComparisonType.Equal },

                               { "leftExpressionColumnPath", "Id" },

                               { "useDisplayValue", false },

                               { "rightExpressionParameterValues", offeringList.ToArray()}};

e.Filters.Add(filter);

С уважением,

Каспаревич Андрей

Эксперт 3-й линии поддержки

Спасибо у меня получилось сделать.

Добрый день, Андрей после переноса в боевую среду, начало выдавать ошибку, скрипт ниже,
LookupFilter не может принять записей больше 1000, высылаю скрин и текст ошибки, прошу помочь исправить ошибку, заранее спасибо.

Page.CallFromQueueEdit.PrepareLookupFilter += delegate (object sender, LookupEditEventArgs e) {
            List<object> callFromQueueList = new List<object>();
 
			var queryCallFromQueue = new Select(UserConnection)
			   .Column("a", "Id")
			   .From("Activity").As("a")
			   .Where("a", "TypeId").IsEqual(Column.Parameter(activityTypeId))
			   .And("a", "StartDate").IsLessOrEqual(Column.Parameter(UserConnection.CurrentUser.GetCurrentDateTime()))
			   .And("a", "StatusId").In(Column.Parameter(NotStartedStatusId), Column.Parameter(InWorkStatusId))
			   .And().OpenBlock("a", "DebtId").Not().IsNull()
			   .Or("a", "ReceivDebtId").Not().IsNull()
               .CloseBlock() as Select;
 
			using (var dbExecutor = UserConnection.EnsureDBConnection()) {
                   using (var dr = queryCallFromQueue.ExecuteReader(dbExecutor)) {
                          while (dr.Read()) {
                                 callFromQueueList.Add((object)UserConnection.DBTypeConverter.DBValueToGuid(dr[0]));
                          }
                   }
            }
			if (callFromQueueList.Count == 0) {
                callFromQueueList.Add((object)Guid.Empty);
            }
 
           e.Filters.Clear();
           var filter = new Dictionary<string, object> { 
                               { "comparisonType", FilterComparisonType.Equal}, 
                               { "leftExpressionColumnPath", "Id"},
                               { "useDisplayValue", false}, 
                               { "rightExpressionParameterValues", callFromQueueList.ToArray()}};
           e.Filters.Add(filter);
 
};

"Бахгельдиев Баглан Абылаевич" написал:
Бахгельдиев Баглан Абылаевич пишет:

Андрей Каспаревич пишет:

Здравствуйте, Баглан!

Уточнил информацию у разработчиков.

Особенность фильтрации на PrepareLookupFilter состоит в том, что либо всё фильтруется через оператор “AND” (по умолчанию) либо через оператор “OR” (Логика устанавливается при помощи параметра)

e.ParametersValue.Add("logicalOperation", LogicalOperationStrict.Or);

Так как в примере идет пересечение AND и OR логики фильтрации, то остается более сложный путь:

1) Написать запрос, с помощью которого отберутся только те Id, которые удовлетворяют условию фильтрации;

2) В фильтрации PrepareLookupFilter фильтровать по найденным Id.

Пример реализации второго варианта:

List<object> offeringList = new List<object>();

var offeringSelect = new Select(UserConnection).

                Column("o", "Id").

                From("Offering").As("o").

                InnerJoin("OfferingType").As("ot").

                On("o", "TypeId").IsEqual("ot", "Id").

                InnerJoin("Service").As("s").

                On("o", "ServiceId").IsEqual("s", "Id").

                InnerJoin("TypeOfService").As("tos").

                On("s", "TypeOfServiceId").IsEqual("tos", "Id").

                Where("ot", "IsService").IsEqual(Column.Parameter(true)).

                And("tos", "Id").IsEqual(Column.Parameter(BusinessServiceTypeId)).              

                And().OpenBlock

                               ("s", "TypeOfServiceRequestId").IsEqual(Column.Parameter(ServiceCallTypeUId)).

                               Or("o", "ServiceId").IsNull().

                               Or().OpenBlock

                                               ("s", "TypeOfServiceRequestId").IsEqual(Column.Parameter(IncidentTypeUId)).

                                               And().Exists(

                                                               new Select(UserConnection).Column("tech", "Id").From("Service").As("tech").

                                                               Where("tech", "ServiceParentId").IsEqual("s", "Id").

                                                               And("tech", "TypeOfServiceId").IsEqual(Column.Parameter(TechServiceTypeId)).

                                                               And("tech", "TypeOfServiceRequestId").IsEqual(Column.Parameter(ServiceCallTypeUId))

                                               ).

                               CloseBlock().

                CloseBlock() as Select;

 

using (var dbExecutor = UserConnection.EnsureDBConnection()) {

                using (var dr = offeringSelect.ExecuteReader(dbExecutor)) {

                               while (dr.Read()) {

                                               offeringList.Add((object)UserConnection.DBTypeConverter.DBValueToGuid(dr[0]));

                               }

                }

}

if (offeringList.Count == 0) {

                offeringList.Add((object)Guid.Empty);

}

e.Filters.Clear();

var filter = new Dictionary<string, object> {

                               { "comparisonType", FilterComparisonType.Equal },

                               { "leftExpressionColumnPath", "Id" },

                               { "useDisplayValue", false },

                               { "rightExpressionParameterValues", offeringList.ToArray()}};

e.Filters.Add(filter);

С уважением,

Каспаревич Андрей

Эксперт 3-й линии поддержки

Спасибо у меня получилось сделать.

Добрый день, Андрей после переноса в боевую среду, начало выдавать ошибку, скрипт ниже,

LookupFilter не может принять записей больше 1000, высылаю скрин и текст ошибки, прошу помочь исправить ошибку, заранее спасибо.

Page.CallFromQueueEdit.PrepareLookupFilter += delegate (object sender, LookupEditEventArgs e) {

            List<object> callFromQueueList = new List<object>();

           

                        var queryCallFromQueue = new Select(UserConnection)

                           .Column("a", "Id")

                           .From("Activity").As("a")

                           .Where("a", "TypeId").IsEqual(Column.Parameter(activityTypeId))

                           .And("a", "StartDate").IsLessOrEqual(Column.Parameter(UserConnection.CurrentUser.GetCurrentDateTime()))

                           .And("a", "StatusId").In(Column.Parameter(NotStartedStatusId), Column.Parameter(InWorkStatusId))

                           .And().OpenBlock("a", "DebtId").Not().IsNull()

                           .Or("a", "ReceivDebtId").Not().IsNull()

               .CloseBlock() as Select;

                           

                        using (var dbExecutor = UserConnection.EnsureDBConnection()) {

                   using (var dr = queryCallFromQueue.ExecuteReader(dbExecutor)) {

                          while (dr.Read()) {

                                 callFromQueueList.Add((object)UserConnection.DBTypeConverter.DBValueToGuid(dr[0]));

                          }

                   }

            }

                        if (callFromQueueList.Count == 0) {

                callFromQueueList.Add((object)Guid.Empty);

            }



           e.Filters.Clear();

           var filter = new Dictionary<string, object> {

                               { "comparisonType", FilterComparisonType.Equal},

                               { "leftExpressionColumnPath", "Id"},

                               { "useDisplayValue", false},

                               { "rightExpressionParameterValues", callFromQueueList.ToArray()}};

           e.Filters.Add(filter);



};

Здравтсвуйте, Баглан!
Как видно из текста ошибки, это ограничение Oracle. Его можно обойти, использовав логическую операцию "OR" для объединения каждых 999 идентификаторов в списке.
(http://stackoverflow.com/questions/17842453/is-there-a-workaround-for-o…)
Таким образом, Вы можете создать двухуровневый список, каждый список из которого будет включать 999 идентификаторов и затем добавить каждый список в отдельный фильтр. Чтобы установить логическую операцию объединения фильтров, используйте код:

e.ParametersValue.Add("logicalOperation", LogicalOperationStrict.Or);
Показать все комментарии

Элемент Чтение данных в событийном подпроцессе нельзя использовать?

Нравится

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

Здравствуйте, Александр!
Это действие нельзя использовать в процессе объекта, так как оно требует сериализации в БД, а процесс объекта не сериализируется.
Если это событийный подпроцесс в обычном БП, то использовать можно.
А в каком контексте возник данный вопрос?

да я сам понял уже, просто хотелось попроще :-)

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

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

Нравится

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

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

Чтобы они появились в карточке необходимо для карточки редактирования раздела в "Рабочих местах" указать признак "Добавить в карточку детали раздела":

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

Андрей, не так.

Есть, например, карточка продажи с деталью "контрагенты"

Необходимо при заполнении поля "Группа компаний", добавить на деталь "контрагенты", контрагентов из выбранной группы.

Илья, а после сохранения записи они там появляются?

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

Илья, я это понял.
По поводу заполнения детали, тут зависит от того, как Вы связывали ее с объектом продажи.
Если связь между деталью и полем на данный момент отсутствует, то можно после добавления группы делать выборку контрагентов, входящих в указанною группу, а потом для каждого контрагента создавать экземпляры (записи) объекта детали.
Пример можно посмотреть на "Странице реестра контактов рассылки", где добавляется группа контактов. Думаю, это то, что нужно.

Реализовал вот так:

Guid affiliationId = Guid.Parse(Page.AffilationEdit.Value.ToString());
 
var userConnection = Page.UserConnection;
var entitySchemaManager = Page.Schema.SchemaManagerProvider.GetManager("EntitySchemaManager") as Terrasoft.Core.Entities.EntitySchemaManager;
var entitySchemaQuery = new EntitySchemaQuery(entitySchemaManager, "AccountToAffiliation");
var accountColumnName = entitySchemaQuery.AddColumn("Account").Name;
entitySchemaQuery.Filters.Add(entitySchemaQuery.CreateFilterWithParameters(FilterComparisonType.Equal, "Affiliation", affiliationId));
var accountCollection = entitySchemaQuery.GetEntityCollection(UserConnection);
 
Guid accountId;
var accountInOpportunityEntitySchema = UserConnection.EntitySchemaManager.GetInstanceByName("AccountInOpportunity");
foreach (var record in accountCollection) {
  accountId = record.GetTypedColumnValue<Guid>("AccountId");
 
  var accountInOpportunityEntity = accountInOpportunityEntitySchema.CreateEntity(UserConnection);
  accountInOpportunityEntity.SetDefColumnValues();
  accountInOpportunityEntity.SetColumnValue("OpportunityId", EntityPrimaryColumnValue);
  accountInOpportunityEntity.SetColumnValue("AccountId", accountId);
  accountInOpportunityEntity.Save();
}

Илья, рад, что получилось.
Спасибо, что делитесь решениями.)

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

Здравствуйте!
Подскажите, пожалуйста, как можно реализовать следующий функционал. Хочу при сохранении записи делать проверку и при определенных условиях не давать сохранять запись и выводить сообщение. Так вот для этого я в событие "Перед сохранением" моего объекта написал скрипт с моей проверкой и возвращал в нем false если не хотел сохранять запись. Но запись все равно сохраняется. Подскажите, пожалуйста что можно сделать чтобы это заработало и как еще вывести в MessagePanel сообщение о причинах при которых эта запись не сохраняется(аналог указан на картинке). Спасибо!

Нравится

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

Может вру, но вот в тройке я возвращаю true, чтобы запись не сохранялась, может и в BPM 5.х также!?
А на счет MessagePanel почитайте тут

Здравствуйте, Павел!
Можно добавить проверки в обработчик нажатия кнопки "ОК" и устанавливать булевский параметр в false, если проверка не прошла. А после Вашего скрипта ставить условный поток, который будет идти дальше в зависимости от параметра.

Можно повесить проверку на нажатие кнопки ОК.
OKBtnClick

В нижнем блоке:

Page.BaseMessagePanel.AddMessage(Warning, MyTextOfMessage, MessageType.Warning);
return true;

Спасибо! Помогло)

Добрый день, возникла похожая задача, но связанная с удалением.
Попытка отредактировать событие на стандартной кнопке удалить, не получилось, в любом случае происходит удаление. Пришлось создать свою кнопку, и скрыть стандартную.
Вот процесс который НЕ работает на стандартной кнопке, но работает на моей добавленной.

Вопрос: как это реализовать через стандартную кнопку?

ScriptTask2:

var AccountAddressCLADR =  UserConnection.EntitySchemaManager.GetInstanceByName("AccountAddressCLADR");
var entity = AccountAddressCLADR.CreateEntity(UserConnection);
var contactId = Page.DataSource.ActiveRowPrimaryColumnValue;
if(contactId == Guid.Empty ){
	Page.ThrowEvent("SaveContactNeeded");
	return true;
}
IsCanDelete = true;
if (entity.FetchFromDB(contactId)) {
 IsCanDelete = !entity.GetTypedColumnValue<Boolean>("ByDefault");
}
return true;

ScriptTask1:

string warningMessageId = "SomeMessageId";
string errorMessage = "Нельзя удалить адрес с установленным признаком <По умолчанию>";
MessagePanel messagePanel = ControlUtilities.FindControl(
                Page.AspPage.Controls[0], "BaseMessagePanel", true) as MessagePanel;
if (messagePanel != null) {
                messagePanel.Remove(warningMessageId);
                messagePanel.AddMessage(warningMessageId, Warning, errorMessage, MessageType.Warning);
}
return true;

На стандартную кнопку навешивается js-обработчик, см. в функции ScriptRegisterClientScriptExecute, унаследованной из BaseGridPage.

	public virtual bool ScriptRegisterClientScriptExecute(ProcessExecutingContext context) {
			string formatString = "{0}.on('click', function(el) {{ {1} }}, this)";
string script = GetRegisterQuestionScript();
if (!string.IsNullOrEmpty(script)) {	
	Page.AddScript(string.Format(formatString, Page.DeleteButton.ClientID, script));
}
...

Чтобы его отключить, можно в функции GetRegisterQuestionScript в своей странице написать вначале

return string.Empty; 

вместо логики.

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

Ошибка возникает внезапно.

Код стандартный

EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
var esqResult = new EntitySchemaQuery(esqManager, "Document");
esqResult.AddColumn ("StatusId");

Entity currentDoc = esqResult.GetEntity(UserConnection, currentDocId);

Работало пять минут назад.
Сейчас перестало.
С какого рожна?
Вылетает на esqResult.AddColumn.

Какой столбец значения не имеет.

Уже не в первый раз приходится все переписывать через Select.
Но это неудобно, когда надо просто запись достать по Id.

Нравится

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

Александр, как вариант - быть может дело в том, что Вы не добавили колонку с первичным ключом (Id), а в момент, когда выполняется GetEntity(UserConnection, currentDocId); система не может по нему отфильтровать и не заполняется коллекция с колонкой StatusId, т.к. результат был null.

точно. спасибо, проверю.

нет. не помогает.

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

Guid parentDocId = new Guid(Page.DataSource.ActiveRow.GetColumnValue("DocumentId").ToString());
 
EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
var esqDocResult = new EntitySchemaQuery(esqManager, "Document");
esqDocResult.AddColumn("Id");
 
Entity parentDoc = esqDocResult.GetEntity(UserConnection, parentDocId);
Guid currentNodeId = parentDoc.GetTypedColumnValue<Guid>("CurrentApprovalNodeId");

даёт
Exception Message: Значение с именем "CurrentApprovalNodeId" не найдено

а в таком

Guid parentDocId = new Guid(Page.DataSource.ActiveRow.GetColumnValue("DocumentId").ToString());
 
EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
var esqDocResult = new EntitySchemaQuery(esqManager, "Document");
esqDocResult.AddColumn("Id");
esqDocResult.AddColumn("CurrentApprovalNodeId");
 
Entity parentDoc = esqDocResult.GetEntity(UserConnection, parentDocId);
Guid currentNodeId = parentDoc.GetTypedColumnValue<Guid>("CurrentApprovalNodeId");

вот так ругается
Exception Message: Элемент коллекции с именем CurrentApprovalNodeId не найден

В чем засада?!!

причем все это скопировано из документации один в один и не работает.

А понял, нужно писать так, т.к. имена колонок генерируются, и их названия не совпадают:

Guid parentDocId = new Guid(Page.DataSource.ActiveRow.GetColumnValue("DocumentId").ToString());
 
EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
var esqDocResult = new EntitySchemaQuery(esqManager, "Document");
var IdColumn = esqDocResult.AddColumn("Id");
var CurAppNodeIdColumn = esqDocResult.AddColumn("CurrentApprovalNodeId");
 
Entity parentDoc = esqDocResult.GetEntity(UserConnection, parentDocId);
Guid currentNodeId = parentDoc.GetTypedColumnValue<Guid>(CurAppNodeIdColumn);

Так то же самое
Exception Message: Элемент коллекции с именем CurrentApprovalNodeId не найден

то есть оно валится на вызове

esqDocResult.AddColumn("CurrentApprovalNodeId");

В общем ничего я не понял, опять через select переписал

Александр, попробуйте так (я опечатался, извините):

Guid parentDocId = new Guid(Page.DataSource.ActiveRow.GetColumnValue("DocumentId").ToString());
 
EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
var esqDocResult = new EntitySchemaQuery(esqManager, "Document");
var IdColumn = esqDocResult.AddColumn("Id");
var CurAppNodeIdColumn = esqDocResult.AddColumn("CurrentApprovalNodeId");
 
Entity parentDoc = esqDocResult.GetEntity(UserConnection, parentDocId);
Guid currentNodeId = parentDoc.GetTypedColumnValue<Guid>(CurAppNodeIdColumn.Name);

попробую, но уже не сегодня. :wink:

"Шамуилов Александр" написал:esqDocResult.AddColumn("CurrentApprovalNodeId");

Попробуйте так:

esqDocResult.AddColumn("CurrentApprovalNode.Id");

Помогло и то и другое :smile:
Данные достаются корректно, все работает, проверял.

if ( IsNew ) {
 
	Guid parentDocId = new Guid(Page.DataSource.ActiveRow.GetColumnValue("DocumentId").ToString());
 
	EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
	var esqDocResult = new EntitySchemaQuery(esqManager, "Document");
	var IdColumn = esqDocResult.AddColumn("Id");
	var CurAppNodeIdColumn = esqDocResult.AddColumn("CurrentApprovalNode.Id");
 
	Entity parentDoc = esqDocResult.GetEntity(UserConnection, parentDocId);
	Guid currentNodeId = parentDoc.GetTypedColumnValue<Guid>(CurAppNodeIdColumn.Name);
 
	var esqAppTypeResult = new EntitySchemaQuery(esqManager, "ApprovalNode");
	var appNodeIdColumn = esqAppTypeResult.AddColumn("Id");
	var appNodeTypeIdColumn = esqAppTypeResult.AddColumn("ApprovalType.Id");
	var appNodeNameColumn = esqAppTypeResult.AddColumn("Name");
 
	Entity appNode = esqAppTypeResult.GetEntity (UserConnection, currentNodeId);
	Guid appNodeTypeId = appNode.GetTypedColumnValue<Guid>(appNodeTypeIdColumn.Name);
	string appNodeTypeName = appNode.GetTypedColumnValue<string>(appNodeNameColumn.Name);
 
	Page.ApprovalTypeLookupEdit.Value = appNodeTypeId;
 
}
 
return true;

Но возникла другая проблема: как мне в скрипте выше (висит на PageLoadComplete карточки редактирования ПОСЛЕ генерации сообщения PageLoadComplete для родительского процесса) установить значение поля ApprovalTypeLookupEdit?

Как написано выше приводит с странным результатам. Страница причем неоперабельна, кнопки Ок Отмена нажимаются но не работают, ее можно только закрыть. И подписей к полям нет......

Если заменить

Page.ApprovalTypeLookupEdit.Value = appNodeTypeId;

на

Page.ApprovalTypeLookupEdit.SuspendAjaxEvents();
Page.ApprovalTypeLookupEdit.SetValueAndText(appNodeTypeId, appNodeTypeName);
Page.ApprovalTypeLookupEdit.ResumeAjaxEvents();

то просто открывается нормально карточка, но поле ApprovalTypeLookupEdit не заполняется.....

Идей, я так понимаю, нет?

Александр, так нельзя:

Page.ApprovalTypeLookupEdit.Value = appNodeTypeId;

Либо так:

Page.ApprovalTypeLookupEdit.SetValue(appNodeTypeId);

Но рекомендую все же так:

Page.DataSource.ActiveRow.SetColumnValue("ApprovalTypeId", appNodeTypeId);

А вот по фигу, извините, конечно :smile:
В смысле что все три варианта не работают :exclaim:

Япппонский городовой!!!:lol:

Надо проставлять значение и в датасорс и поле лукапа!!

Вот так работает:

Page.DataSource.ActiveRow.SetColumnValue ("ApprovalTypeId", appNodeTypeId);
Page.ApprovalTypeLookupEdit.SetValueAndText (appNodeTypeId, appNodeTypeName);	

BPMOnline Reality (Версия 5.4.1.256)

Аналогичный код у меня не работает:

    //select Tenants
    var esqTenant = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Tenant");
    esqTenant.AddColumn("Id");
    esqTenant.AddColumn("Account");
    esqTenant.AddColumn("Project");
    esqTenant.AddColumn("Facility");
    var ownerCol = esqTenant.AddColumn("Account.Owner");
    esqTenant.AddColumn("DueDate");
    //filters
    esqTenant.Filters.LogicalOperation = LogicalOperationStrict.Or;
    esqTenant.Filters.Add(esqTenant.CreateFilterWithParameters(
	    FilterComparisonType.Equal, "DueDate", dd1));
    esqTenant.Filters.Add(esqTenant.CreateFilterWithParameters(
	    FilterComparisonType.Equal, "DueDate", dd30));
    //result
    Guid accountId;
    string accountName;
 
    var tenantCollection = esqTenant.GetEntityCollection(UserConnection);
    foreach (var record in tenantCollection) {
	    Guid ownerId = record.GetTypedColumnValue<Guid>(ownerCol.Name); //1
	    accountId = record.GetTypedColumnValue<Guid>("AccountId"); //2
	    accountName = record.GetTypedColumnValue<String>(record.Schema.Columns.GetByName("Account").DisplayColumnValueName); //3
    }

говорит "Значение с именем "Account_Owner" не найдено" (строка "1")

а также объясните почему в строке "2" нужно писать название поля как в базе (с Id), а в строке "3" - как в объекте ?

Хороший вопрос.....ТП, вы гиде? :smile:

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

В запросе типа EntitySchemaQuery необходимо название колонок писать так как в таблице объекта:

esqTenant.AddColumn("Id");
    esqTenant.AddColumn("AccountId");
    esqTenant.AddColumn("ProjectId");
    esqTenant.AddColumn("FacilityId");
    var ownerCol = esqTenant.AddColumn("Account.OwnerId");
    //или var ownerCol = esqTenant.AddColumn("Account.Owner.Id");

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

var AccountId = esqTenant.AddColumn("Account");
accountId = record.GetTypedColumnValue<Guid>(AccountId.Name);

Ошибку вызывает строка "1"

Guid ownerId = record.GetTypedColumnValue<Guid>(ownerCol.Name);

если ее убрать все работает

если писать

esqTenant.AddColumn("AccountId");

то "Элемент коллекции с именем AccountId не найден"

Лариса, что-то я запутался :)

Если убрать

Guid ownerId = record.GetTypedColumnValue<Guid>(ownerCol.Name);

то все работает даже с

esqTenant.AddColumn("AccountId");

или нет?

И колонка AccountId точно есть в таблице? Может она называется как-то CustomerId?
Только что у себя попробовал сделать запрос с контактов с полями OwnerId и AccountId - без ошибок.

Если убрать

Guid ownerId = record.GetTypedColumnValue<Guid>(ownerCol.Name);

то остальной код работает.

Если писать как Вы предлагали в #18, т.е.

esqTenant.AddColumn("AccountId");

то возникает ошибка "Элемент коллекции с именем AccountId не найден".

Поле в схеме объекта называется Account, в базе AccountId

А если написать:
var ownerCol = esqTenant.AddColumn("Account.Owner.Id");

То со строкой

Guid ownerId = record.GetTypedColumnValue<Guid>(ownerCol.Name);

работает?

Да, так работает.
Спасибо!

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