26.10.2009, 09:10 | #1 |
Участник
|
Бизнес-процесс: применение определенного алгоритма к каждой записи CRMGrid
Доброе утро! Нужно создать бизнес-процесс, который бы пробегал по всем записям данной сущности и если у записи определенный атрибут установлен в Активен, то получить из этой записи определенные атрибуты, как параметры и выполнить заданный алгоритм. Начал писать правило для бизнес-процесса, для этого воспользовался примером из книги Майка Снайдера:
Код: using System; using System.Workflow.ComponentModel; using System.Workflow.Activities; using Microsoft.Crm.Workflow; namespace BP_CRMScaner { [CrmWorkflowActivity("Выполнить сканирование", "Сканирование WEB-ресурсов")] public partial class Activity1 : SequenceActivity { protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { //получение контекста IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService)); IWorkflowContext ctx = contextService.Context; //Здесь выполняется пользовательская логика //Доступ к свойствам ввода и вывода осуществляется следующим образом this.InputExample = "foo"; this.OutputExample = this.InputExample + "bar"; return base.Execute(executionContext); } //Задание свойств ввода public static DependencyProperty InputExampleProperty = DependencyProperty.Register("InputExample", typeof(string), typeof(Activity1)); [CrmInput("InputExample")] public string InputExample { get { return (string)base.GetValue(InputExampleProperty); } set { base.SetValue(InputExampleProperty, value); } } //Задание свойства вывода public static DependencyProperty OutputExampleProperty = DependencyProperty.Register("OutputExample", typeof(string), typeof(Activity1)); [CrmOutput("OutputExample")] public string OutputExample { get { return (string)base.GetValue(OutputExampleProperty); } set { base.SetValue(OutputExampleProperty, value); } } } } Последний раз редактировалось Tarasov E; 26.10.2009 в 09:31. |
|
26.10.2009, 09:39 | #2 |
Moderator
|
Опишите задачу на конкретном примере, пожалуйста. Мне кажется что вы не верно понимаете суть бизнес процессов. БП используются для обработки различных событий, а не для обработки базы.
Чтобы вычитать запись по определенными критериями нужно использовать метод CrmService.RetrieveMultiple, а не перебирать все записи.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
26.10.2009, 09:52 | #3 |
Участник
|
Описываю более подробно: Есть сущность new_web с множеством записей. У каждой записи есть набор атрибутов: периодичность сканирования, стутус(активно, отключено) и атрибуты-парметры, которые необходимо передать на выполнение в определенный алгоритм. Так вот, нужен бизнес-процесс, который раз в "Периодичность" обращается к записи(у каждой записи периодичность своя, хотя на начальном этапе можно попробовать задать общую периодичность в самом БП), получает атрибуты-параметры и выполняет определенный алгоритм, результатом которого будет создание некоторых файлов на диске.
Ниже прикрепляю скрин: при запуске бизнес процесса, если состояние "Активно", из записи (я полагаю по GUID) мы получаем определенные атрибуты и выполняем алгоритм. |
|
26.10.2009, 10:07 | #4 |
Moderator
|
БП не умеет стартовать по расписанию. Проще написать windows службу, которая будет выполнять все описанные выше операции.
p.s. Очень и очень странная задача для CRM системы! В чем суть сканирования, если не секрет?
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
26.10.2009, 10:23 | #5 |
Участник
|
Суть в том, чтобы просканировав заданные сайты - получать только интересующую информацию с их вэб-ресурсов. Допустим только новости, а весь остальной мусор отбрасывать.
А если немного схитрить: сделать 2 поля: дата сканирования и периодичность. за 24 часа до наступления "Дата сканирования" выполнить бизнес-процесс и прибавить к "Дата сканирования" периодичность. Как то так? И кстати да, неверно понял, мне на самом деле не нужно пробегать по всем записям из CRMGrid'а, ведь бизнес-процесс будет реагировать на "Дату сканирования" каждой записи в отдельности". Последний раз редактировалось Tarasov E; 26.10.2009 в 11:01. |
|
26.10.2009, 11:46 | #6 |
Moderator
|
Ну, реализация задач с повторением уже не раз обсуждалась, попробуйте поискать эти топики. Скажу сразу - нужно долго извращаться. В CRM 5.0 они заявлены как стандартный функционал.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
26.10.2009, 15:51 | #7 |
Moderator
|
Я поддерживаю Артема с его предложением написать Windows службу.
|
|
27.10.2009, 09:05 | #8 |
Консультант-джедай
|
Цитата:
Сообщение от Tarasov E
Суть в том, чтобы просканировав заданные сайты - получать только интересующую информацию с их вэб-ресурсов. Допустим только новости, а весь остальной мусор отбрасывать.
А если немного схитрить: сделать 2 поля: дата сканирования и периодичность. за 24 часа до наступления "Дата сканирования" выполнить бизнес-процесс и прибавить к "Дата сканирования" периодичность. Как то так? И кстати да, неверно понял, мне на самом деле не нужно пробегать по всем записям из CRMGrid'а, ведь бизнес-процесс будет реагировать на "Дату сканирования" каждой записи в отдельности". http://mmcrm.ru/?p=385
__________________
Крокодил, крокожу и буду крокодить. Человек человеку - волк , а зомби зомби - зомби. Экстремал и буду экстремать! Блога |
|
|
За это сообщение автора поблагодарили: Tarasov E (1). |
27.10.2009, 09:59 | #9 |
Участник
|
|
|
27.10.2009, 11:53 | #10 |
Участник
|
Появился вопрос по первому способу:
Можно ли при обновление - параметр обновления брать из другого поля, чтобы для каждой записи была своя периодичность выполнения бизнес процесса? Например как-нибудь так: {час.:new_period.DataValue После ...и т.д} То что мне нужно более понятно обрисовано на скрине |
|
27.10.2009, 12:17 | #11 |
Moderator
|
Можно: нужно писать кастомный степ для плагина, который прибавит к дате произвольное число дней и запишет в нужную ячейку.
Еще раз повторяю: вы пытаетесь использовать workflow не по назначению! Ожидание и повторение - не его конек! Требуют хранить расписание в CRM - ради бога, храните. Но заведите стандартный сервис, который будет читать из CRM данные по расписанию, выполнять сканирование и заливать данные обратно. Кучу времени себе сэкономите!
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
|
За это сообщение автора поблагодарили: Tarasov E (1). |
27.10.2009, 13:19 | #12 |
Участник
|
Хорошо, про кастомный стэп понятно...вернемся все же к первой части вопроса: как в workflow activity получить данные из полей формы, для их обработки?
|
|
27.10.2009, 13:27 | #13 |
Чайный пьяница
|
Цитата:
Регистрируете инпут проперти - лукапом на сущность из которой планируете получить данные, в коде степа при помощи Retrieve вычитываете данную сущность, суммируете дату и период, на выход (output property) отдаёте полученную суммированием дату. Собственно всё.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
27.10.2009, 14:19 | #14 |
Участник
|
Цитата:
Сообщение от a33ik
Точно так же - при прмрщи кастомного экшена.
Регистрируете инпут проперти - лукапом на сущность из которой планируете получить данные, в коде степа при помощи Retrieve вычитываете данную сущность, суммируете дату и период, на выход (output property) отдаёте полученную суммированием дату. Собственно всё. Код: public static DependencyProperty InputExampleProperty = DependencyProperty.Register("InputExample", typeof(string), typeof(Activity1)); [CrmInput("InputExample")] public string InputExample { get { return (string)base.GetValue(InputExampleProperty); } set { base.SetValue(InputExampleProperty, value); } Далее мы уже с помощью retrieve сможем выдирать атрибуты и обрабатывать как нам угодно? А что за тип данных должен, чтобы в настройках стэпа указать ссылку на сущность? typeof(Lookup) почему то он не понимает... Последний раз редактировалось Tarasov E; 27.10.2009 в 14:22. |
|
27.10.2009, 14:30 | #15 |
Чайный пьяница
|
Цитата:
Сообщение от Tarasov E
Тоесть если я правильно понял то пример из первого сообщения
Код: public static DependencyProperty InputExampleProperty = DependencyProperty.Register("InputExample", typeof(string), typeof(Activity1)); [CrmInput("InputExample")] public string InputExample { get { return (string)base.GetValue(InputExampleProperty); } set { base.SetValue(InputExampleProperty, value); } Далее мы уже с помощью retrieve сможем выдирать атрибуты и обрабатывать как нам угодно? А что за тип данных должен, чтобы в настройках стэпа указать ссылку на сущность? typeof(Lookup) почему то он не понимает...
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
|
За это сообщение автора поблагодарили: Tarasov E (1). |
27.10.2009, 14:31 | #16 |
Участник
|
Цитата:
You can use the System.Workflow.ComponentModel.PersistOnClose...
|
|
27.10.2009, 14:37 | #17 |
Чайный пьяница
|
Сборки, референсы на которые нужны для CustomWorkflowAction.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
29.10.2009, 11:19 | #18 |
Чайный пьяница
|
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
29.10.2009, 11:26 | #19 |
Участник
|
Спасибо, a33ik, с библиотеками разобрался, сделал как было указано выше:
Код: namespace BP_CRMScaner { [CrmWorkflowActivity("Выполнить сканирование", "Сканирование WEB-ресурсов")] public class Activity1 : SequenceActivity { protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { //получение контекста IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService)); IWorkflowContext ctx = contextService.Context; //Здесь выполняется пользовательская логика return base.Execute(executionContext); } //Задание свойств ввода public static DependencyProperty ScanProperty = DependencyProperty.Register("Scaner", typeof(Lookup), typeof(Activity1)); [CrmInput("Субъект сканирования")] [CrmReferenceTarget("new_web")] public Lookup Scaner { get { return (Lookup)base.GetValue(ScanProperty); } set { base.SetValue(ScanProperty, value); } } } } Цитата:
Error 1 Could not create activity of type 'BP_CRMScaner.Activity1'. System.ArgumentException: Type 'BP_CRMScaner.Activity1' does not define a static dependency property with name 'ScanerProperty'.
Parameter name: ownerType at System.Workflow.ComponentModel.DependencyProperty.ValidateAndRegister(String name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, Type validatorType, Boolean isRegistered) at System.Workflow.ComponentModel.DependencyProperty.Register(String name, Type propertyType, Type ownerType) at BP_CRMScaner.Activity1..cctor() |
|
29.10.2009, 11:31 | #20 |
Чайный пьяница
|
Цитата:
Сообщение от Tarasov E
Спасибо, a33ik, с библиотеками разобрался, сделал как было указано выше:
Код: namespace BP_CRMScaner { [CrmWorkflowActivity("Выполнить сканирование", "Сканирование WEB-ресурсов")] public class Activity1 : SequenceActivity { protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { //получение контекста IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService)); IWorkflowContext ctx = contextService.Context; //Здесь выполняется пользовательская логика return base.Execute(executionContext); } //Задание свойств ввода public static DependencyProperty ScanProperty = DependencyProperty.Register("Scaner", typeof(Lookup), typeof(Activity1)); [CrmInput("Субъект сканирования")] [CrmReferenceTarget("new_web")] public Lookup Scaner { get { return (Lookup)base.GetValue(ScanProperty); } set { base.SetValue(ScanProperty, value); } } } } В чем проблема? Вроде все делал по образцу Код: namespace BP_CRMScaner { [CrmWorkflowActivity("Выполнить сканирование", "Сканирование WEB-ресурсов")] public class Activity1 : SequenceActivity { protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { //получение контекста IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService)); IWorkflowContext ctx = contextService.Context; //Здесь выполняется пользовательская логика return base.Execute(executionContext); } //Задание свойств ввода public static DependencyProperty ScanerProperty = DependencyProperty.Register("Scaner", typeof(Lookup), typeof(Activity1)); [CrmInput("Субъект сканирования")] [CrmReferenceTarget("new_web")] public Lookup Scaner { get { return (Lookup)base.GetValue(ScanerProperty); } set { base.SetValue(ScanerProperty, value); } } } }
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|