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

Нам нужно запустить интеграцию с одним сайтом, но api там нет, поэтому мы парсим страницу и забираем нужные данные. Парсер реализован как конфигурационный сервис на C#.

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

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

Каким образом это можно реализовать в системе?

Заранее спасибо!)

Нравится

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

Добрый день.

Классических варианта 2:

1. Хранение на уровне приложения. Статическая переменная в вашем классе или другом отдельном классе по работе с Cookie (например можно завести класс CookieManager), в которой будет храниться получаемый вами CookieContainer.

2. Хранение на уровне Redis. В общем-то Redis позволяет хранить данные любого типа по принципу "ключ-значение". 

Добрый день.

Классических варианта 2:

1. Хранение на уровне приложения. Статическая переменная в вашем классе или другом отдельном классе по работе с Cookie (например можно завести класс CookieManager), в которой будет храниться получаемый вами CookieContainer.

2. Хранение на уровне Redis. В общем-то Redis позволяет хранить данные любого типа по принципу "ключ-значение". 

Толмачев Дмитрий Юрьевич,

Дмитрий, спасибо! будем пробовать).

 

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

Товарищи помогите.

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

Как добавить пакет Diagnostics? Я так понимаю его вообще нет?

 

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

 

Вот что получаю

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

 

Сгенерированный исходный код:

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

Нравится

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

Подскажите, пожалуйста, что у Вас располагается на 49 строчке в сгенерированном исходном коде?

И не пробовали Вашу 11 строчку в методе заменить на 

System.Diagnostics.ProcessStartInfo p = new System.Diagnostics.ProcessStartInfo();

?

Спасибо, если прописать полный путь:  new System.Diagnostics.ProcessStartInfo()  то все нормально, не удобно, но сойдет

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

Например, есть запрос на sql такого вида:

declare @DocumentTypeId uniqueidentifier

declare @InvoiceTypeId uniqueidentifier

update I

set

    I.TypeId = @InvoiceTypeId

from Invoice I

    join Document D on D.Id = I.DocumentId

where D.TypeId = @DocumentTypeId

Можно ли его реализовать с помощью класса Update на C#?

Нравится

1 комментарий
Вопрос
C#

Приветы, подскажите

Как писать на c# и чтобы это было доступно с клиента?

Можно пример wcf? (с одним-двумя методами, например, который что-нибудь из БД платформы выдает в JSON) 

Нравится

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

Доброго времени суток!

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

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

Нравится

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

Здравствуйте, элемент "Выполнить задачу" после себя предоставляет все свои колонки включая Id, следовательно по этому Id можно данную задачу видоизменять после создания, см. скр:

"Максим Шевченко" написал:

Здравствуйте, элемент "Выполнить задачу" после себя предоставляет все свои колонки включая Id, следовательно по этому Id можно данную задачу видоизменять после создания, см. скр:


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

В момент создания? Тогда либо использовать параметры из расширенного режима, они заполняют именно до сохранения в бд активности значения:


Либо если нужных колонок нет в списке, то можете вообще создать свою версию элемента "Выполнить задачу" расширив его нужными колонками, и дописав их заполнение в методе "CreateActivity". Либо если бизнес логика позволяет, то заполнить их по какому-то условию в событийном бп перед сохранением объекта "Активность".

А скрипт о котором говорится вначале, все равно работает после сохранения и аналогичен тому что я предложил в своем первом комментарии.

"Максим Шевченко" написал:А скрипт о котором говорится вначале, все равно работает после сохранения и аналогичен тому что я предложил в своем первом комментарии.

Просто у этого скрипта жестко указан контекст выполнения и он не видит других глобальных параметров текущего БП.

Кисловский Михаил Андреевич,

Доброго дня. Подскажите, получилось ли решить Вашу задачу?

У меня такая же, и не могу найти вариантов, если действительно код в элементе не видит параметров процесса..

 

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

Мамлютов Виктор Александрович, разобрались давно.

Пример того как можно делать Update через данную вкладку:

 

activity.SetColumnValue("IsCheckOfTerms", true); //название параметра в объекте активности, потом значение которое необходимо установить

activity.Save();

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

Добрый день!

Появилась потребность формировать фильтры для динамических групп автоматически, собственно, нашел как они формируются из JS-ного кода и хранятся в таблице [раздел]Folder в виде шестнадцатеричного кода. Вопрос, как формировать и сериализовывать их для записи в таблицу?

Нравится

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

"Шамшин Олег" написал:Вопрос, как формировать и сериализовывать их для записи в таблицу?

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

Олег,

а какую бизнес-задачу Вы хотите решить таким образом?

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

Заранее благодарю за ответ ;-)

"Алла Савельева" написал:а какую бизнес-задачу Вы хотите решить таким образом?

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

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

"Алла Савельева" написал:а какую бизнес-задачу Вы хотите решить таким образом?

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

"Шамшин Олег" написал:статические группы не работают в 7.10

Это не решает задачу, но в 7.10 вместо статических групп можно использовать тэги, по которым уже строить динамические группы.

Олег,

Можно реализовать некий справочник, который будет хранить структуру каталога продуктов. В каждом продукте добавить поле (назовем его [Каталог]), которое будет ссылаться на этот справочник и хранить принадлежность продукта к определенному каталогу.
На основании информации в поле [Каталог] настроить структуру динамических групп, какой угодно вложенности.

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

Олег, а какой именно у вас продукт bpm'online? В Enterprise этот вопрос решен уже

"Владимир Соколов" написал:какой именно у вас продукт bpm'online

Владимир, BPMOnline Sales Enterprise 7.10.1, а каким образом вопрос решен?

"Алла Савельева" написал:такой способ не позволяет менять саму структуру каталога

Алла, рассматривали похожий вариант - не подходит, т.к. надо менять структуру без участия пользователя/людей вообще, то бишь автоматически.

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

Группа = каталог (название группы - это название каталога), а продукт, который принадлежит каталогу входит в группу.

Если настроить импорт записей соответственно, то получится менять структуру автоматически.
Если появляется новый каталог, то добавляется новая статическая группа, в которую добавляются нужные продукты.
Из плюсов такого подхода: возможность хранения каталога в виде иерархического списка сколько угодно уровней вложенности.
Таким образом в Bpm'online для этого уже все реализовано, остается только вопрос в реализации импорта, а это фактически запись нужных данных в нужные таблицы :wink:

Небольшая поправка, если у Вас продукт bpm'online sales enterprise 7.10.1, тогда статических групп у Вас нет (они есть только в продукте bpm'online marketing), а вместо них есть тэги, о которых писал Владимир.

"Шамшин Олег" написал:Владимир, BPMOnline Sales Enterprise 7.10.1, а каким образом вопрос решен?

Олег, мне кажется, функционал каталога продуктов вам поможет - как раз динамически формируется структура: https://academy.terrasoft.ua/documents/sales-enterprise/7-10/katalog-pr…

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

Добрый день! Столкнулся с проблемой. В моем БП имеется некий с# код, который выполняется около 10 секунд (сервер быстрее не дает) и мой БП не идет дальше и замораживает страницу на эти 10 секунд. Не подскажите возможно ли выполнить мой c# код в отдельном потоке?
Версия 7.7

Нравится

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

Добрый день, Алексей!

Не уверен насчет 7.7, но начиная с 7.9 точно работает такой костыль(фича?). Можно поставить перед этим скрипт-таском (или же в начале всего процесса) таймер на 1 с, таким образом его выполнение произойдет в другом потоке.

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

Коллеги, доброе утро!
В C# блоке бизнес-процесса выполняется следующий скрипт:

 Select caseDeadlineResponseSelect = new Select(userConnection).
         Column("Case", "id").As("CaseId").
         From("Case").
         Where("Case", "StatusId").IsEqual(Column.Parameter(caseStatusNew))
         .And("Case", "NrbSentDeadlineResponse").IsEqual(Column.Parameter("0"))
         .And(Func.DateDiff(DateDiffQueryFunctionInterval.Minute, Column.Const(dateNow), new QueryColumnExpression("RegisteredOn"))/
         Func.DateDiff(DateDiffQueryFunctionInterval.Minute, new QueryColumnExpression("ResponseDate"), new QueryColumnExpression("RegisteredOn"))).IsGreaterOrEqual(Column.Parameter(0.9))
         as Select;

Проблема в том, что в блоке WHERE в частности где идет идет деление дат, происходит округление в большую сторону, т.о как правило результат выражения
Func.DateDiff(DateDiffQueryFunctionInterval.Minute, Column.Const(dateNow), new QueryColumnExpression("RegisteredOn"))/
         Func.DateDiff(DateDiffQueryFunctionInterval.Minute, new QueryColumnExpression("ResponseDate"), new QueryColumnExpression("RegisteredOn")))
всегда равен больше единицы. В обычном SQL, я бы произвел конвертацию делимого и делителя:
CONVERT(decimal(10,2),DATEDIFF(MINUTE, GETDATE(), RegisteredOn))/
CONVERT(decimal(10,2),DATEDIFF(MINUTE, ResponseDate, RegisteredOn))

Но как произвести конвертацию в C# блоке я не понял. Я использовал функцию CAST, но не смог подобрать DBDatValueType.
Подскажите, как все таки произвести вычислениях хотя бы до десятых долей.

Нравится

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

В принципе, можно вписать произвольный SQL-код через Column.SqlText.
Примеры работы с ним можно найти в конфигурации. Вот тут тоже работают с датами:

var campaignPurchaseQtyCountSelect = new Select(UserConnection)
		.Column(Func.Count("Id"))
		.From("CampaignPurchaseQtyCount")
		.Where("CampaignId").IsEqual("Campaign", "Id")
		.And("CardId").IsEqual(Column.Parameter(cardId))
		.And(Column.SqlText("DATEDIFF(D, 0, [PurchaseDate])")).IsEqual(Column.SqlText("DATEDIFF(D, 0, @purchaseDate)"));
if (purchaseEntity.GetTypedColumnValue<Guid>("TypeId").Equals(Terrasoft.Configuration.PurchaseConsts.ReturnTypeUId)) {
	campaignPurchaseQtyCountSelect
		.And("IsRewarded").IsEqual(Column.Parameter(false));
}

BEHOLD!!!!

DBDataValueType valueType = userConnection.DataValueTypeManager.GetInstanceByUId(DataValueType.FloatDataValueTypeUId) as DBDataValueType;
 
DateDiffQueryFunction diff1 = Func.DateDiff(DateDiffQueryFunctionInterval.Day, Column.Const(DateTime.UtcNow), new QueryColumnExpression("CreatedOn")),
	diff2 = Func.DateDiff(DateDiffQueryFunctionInterval.Day, new QueryColumnExpression("TmResponseDate"), new QueryColumnExpression("CreatedOn"));
 
QueryColumnExpression exp1 = new QueryColumnExpression(diff1), exp2 = new QueryColumnExpression(diff2);
CastQueryFunction cast1 = Func.Cast(exp1, valueType), cast2 = Func.Cast(exp2, valueType);
 
 
QueryColumnExpression exp3 = new QueryColumnExpression(cast1), exp4 = new QueryColumnExpression(cast2);
QueryColumnExpression result = QueryColumnExpression.Divide(exp3, exp4);
 
Select decSelect = new Select(userConnection).Top(1)
	.Column(result)
	.From("TmNews")
as Select;
return decSelect.ExecuteScalar<float>();

В итоге выдаёт 0.6666667 на тестовом примере. Но эт жесть, конечно:smile:

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

Добрый день!

Коллеги, подскажите, пожалуйста, какой наиболее корректный способ массово (в цикле) удалять записи в БД с помощью ESQ?

Вариант с foreach:

EntitySchema schemaDeleteEntity =userConnection.EntitySchemaManager.GetInstanceByName(EntityName);
EntitySchemaQuery esqDeleteEntity = new EntitySchemaQuery(schemaDeleteEntity);
esqDeleteEntity.AddAllSchemaColumns();
esqDeleteEntity.Filters.Add(esqDeleteEntity.CreateFilterWithParameters(FilterComparisonType.Equal, AccountIdField, AccountId));
EntityCollection entitiesDeleteEntity = esqDeleteEntity.GetEntityCollection(userConnection);
  foreach (Entity deleteentity in  entitiesDeleteEntity)
  {
      deleteentity.Delete();
  }

возвращает exception "Коллекция была изменена после создания экземпляра перечислителя."

Если заменить на простой for:

for(int i = entitiesDeleteEntity.Count-1;i>=0;i--)
{
        entitiesDeleteEntity[i].Delete();
}

Код отрабатывает корректно, но при нагрузке удаление периодически вызывает exception о незавршённых транзакциях вида:
Данный SqlTransaction завершен; его повторное использование невозможно.   в System.Data.SqlClient.SqlTransaction.ZombieCheck()
   в System.Data.SqlClient.SqlTransaction.Rollback()
   в Terrasoft.Core.DB.DBExecutor.RollbackTransaction()
   в Terrasoft.Core.Entities.Entity.ExecuteDelete(Delete delete, Object keyValue)
   в Terrasoft.Core.Entities.Entity.Delete(Object keyValue)
   в Terrasoft.Core.Entities.Entity.Delete()

Как всё-таки правильнее?

Спасибо!

Нравится

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

Добрый день!
Для массового удаления лучше не использовать EntitySchemaQuery, так как ESQ накладывает права на запрос. Лучше всего использовать либо класс Delete, или же использовать хранимую процедуру.
Единственный случай, когда нужно использовать ESQ - это если вам нужно запускать процессы, которые настроенны на сигнал "удаления записи", но и в этом случае лучше найти альтернативу по запуску доп логики после удаления

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

Добрый день!
При попытке в VisualStudio 2012 сделать Attach к процессу "w3wp.exe", в окне Output появляются сообщения вида:

The thread '' (0x2aac) has exited with code 0 (0x0).
The thread '' (0x1c14) has exited with code 0 (0x0).
The thread '' (0x14a0) has exited with code 0 (0x0).

Attach не происходит - пустая точка останова
Пожалуйста помогите разобраться!

Нравится

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

Здравствуйте, Антон.

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

"Сергей Кy6риш" написал:

Здравствуйте, Антон.

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

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

С уважением,

Группа компаний Terrasoft

Здравствуйте Сергей!
У меня в списке всего один процесс "w3wp.exe", сделал чтобы он запускается под тем пользователем под которым выполнен вход в систему. Теперь Attach проходит дальше, но всё равно не до конца, всё также появляются сообщения вида

The thread '' (0x24f0) has exited with code 0 (0x0).
The thread '' (0x1b30) has exited with code 0 (0x0).
The thread '' (0x2544) has exited with code 0 (0x0).

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

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

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