22.04.2014, 12:58 | #1 |
Участник
|
Подсчёт записей
Добрый день!
В опросе есть токены и ниже есть поля (показано на картинке), нужно сосчитать сколько всего токенов, сколько стартовавших и сколько финишировало. Нужно сделать именно плагин, вот этот код поставил на post-operation, но ошибка (прикрепил лог): Код: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xrm.Sdk; using Bum.Survey.CRM.Plugin.BaseLib; using Microsoft.Xrm.Sdk.Query; namespace Bum.Survey.CRM.Plugin { public class SurveyAIU : IPlugin { public void Execute(IServiceProvider serviceProvider) { var process = new SurveyAIUProcess(serviceProvider); process.LoadEntity(); if (!process.ValidateEntityName("bf_survey")) return; if (!process.ValidateMessage(MessageName.Create, MessageName.Update)) return; process.Run(); } } class SurveyAIUProcess : bf_PluginProcess { public override void Execute() { Entity survey = crmService.Retrieve(TargetEntity.LogicalName, TargetEntity.Id, new ColumnSet(true)); QueryExpression token = new QueryExpression() { EntityName = "bf_surveytoken", ColumnSet = new ColumnSet(true) }; token.Criteria.AddCondition("bf_surveytoken_survey", ConditionOperator.Equal, TargetKey.Id); List<Entity> surveyTokens = crmService.RetrieveMultiple(token).Entities.ToList(); if (surveyTokens.Count > 0) { survey["bf_survey_tkcnt"] = surveyTokens.Count.ToString(); crmService.Update(survey); } } public SurveyAIUProcess(IServiceProvider serviceProvider) : base(serviceProvider) { } } } |
|
22.04.2014, 14:53 | #2 |
Участник
|
1. Вот этот вот апдейт crmService.Update(survey); вызывает Ваш плагин снова и снова. Что получается? Бесконечный цикл. Но СРМ умный и останавливает это после 8-го раза.
Для того чтобы это не случалось нужно либо делать это в пре-плагине. Или добавлять как-то флаг, который бы говорил нужно ли делать апдейт или нет. 2. Вместо вот этого: Entity survey = crmService.Retrieve(TargetEntity.LogicalName, TargetEntity.Id, new ColumnSet(true)); Используйте пост-имедж. Хотя в Вашем коде и этого не нужно. Для апдета достаточно следующего кода: Entity survey = new Entity(TargetEntity.LogicalName); survey.Id = TargetEntity.Id; survey["bf_survey_tkcnt"] = surveyTokens.Count.ToString(); crmService.Update(survey); |
|
|
За это сообщение автора поблагодарили: Lavdislav (1). |
22.04.2014, 15:55 | #3 |
Участник
|
Цитата:
Сообщение от Ksani
1. Вот этот вот апдейт crmService.Update(survey); вызывает Ваш плагин снова и снова. Что получается? Бесконечный цикл. Но СРМ умный и останавливает это после 8-го раза.
Для того чтобы это не случалось нужно либо делать это в пре-плагине. Или добавлять как-то флаг, который бы говорил нужно ли делать апдейт или нет. 2. Вместо вот этого: Entity survey = crmService.Retrieve(TargetEntity.LogicalName, TargetEntity.Id, new ColumnSet(true)); Используйте пост-имедж. Хотя в Вашем коде и этого не нужно. Для апдета достаточно следующего кода: Entity survey = new Entity(TargetEntity.LogicalName); survey.Id = TargetEntity.Id; survey["bf_survey_tkcnt"] = surveyTokens.Count.ToString(); crmService.Update(survey); |
|
22.04.2014, 20:13 | #4 |
Участник
|
Вы не поняли.
В первом пунке описано почему ошибка: потому что у Вас зациклен плагин. А во втором просто замечание по коду. Теперь, чтобы не было повторного вызова кода плагина можно добавить в начале плагина проверку X++: if(!TargetEntity.Contains("bf_survey_tkcnt")) { QueryExpression token = new QueryExpression() { EntityName = "bf_surveytoken", ColumnSet = new ColumnSet(true) }; token.Criteria.AddCondition("bf_surveytoken_survey", ConditionOperator.Equal, TargetKey.Id); List<Entity> surveyTokens = crmService.RetrieveMultiple(token).Entities.ToList(); if (surveyTokens.Count > 0) { Entity survey = new Entity(TargetEntity.LogicalName); survey.Id = TargetEntity.Id; survey["bf_survey_tkcnt"] = surveyTokens.Count.ToString(); crmService.Update(survey); } } |
|
23.04.2014, 17:02 | #5 |
Участник
|
Спасибо, помогло, разобрался. Теперь другая трабла, хочу чтобы при удалении токена, обновлялось поле в опросе (тоесть если удалю то на 1 меньше), но вот кидает ошибку (лог прикрепляю). Код вот:
Код: if (executionContext.MessageName == MessageName.Delete) { QueryExpression surveyz = new QueryExpression() { EntityName = "bf_survey", ColumnSet = new ColumnSet(true) }; surveyz.Criteria.AddCondition("bf_surveyid", ConditionOperator.Equal, TargetEntity.GetAttributeValue<EntityReference>("bf_surveytoken_survey").Id); List<Entity> surveylists = crmService.RetrieveMultiple(surveyz).Entities.ToList(); foreach (var surveylist in surveylists) { QueryExpression token = new QueryExpression() { EntityName = "bf_surveytoken", ColumnSet = new ColumnSet(true) }; token.Criteria.AddCondition("bf_surveytoken_survey", ConditionOperator.Equal, surveylist.Id); List<Entity> surveyTokens = crmService.RetrieveMultiple(token).Entities.ToList(); surveylist["bf_survey_tkcnt"] = surveyTokens.Count - 1; crmService.Update(surveylist); } } Последний раз редактировалось Lavdislav; 23.04.2014 в 17:24. Причина: Прикрепил ошибку |
|
23.04.2014, 17:18 | #6 |
Чайный пьяница
|
А может ещё ошибку сюда прикрепите?
Но моя гипотеза в следующем - при удалении записи в Target приходит не Entity а EntityReference. Для получения значения поля из лукапа рекомендую использовать Pre-Image удаляемой записи.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
23.04.2014, 17:24 | #7 |
Участник
|
|
|
23.04.2014, 17:36 | #8 |
Чайный пьяница
|
Скорее всего я прав. Полный код плагина предоставьте, пожалуйста.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
23.04.2014, 17:39 | #9 |
Участник
|
X++: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xrm.Sdk; using Bum.Survey.CRM.Plugin.BaseLib; using Microsoft.Xrm.Sdk.Query; using Microsoft.Xrm.Sdk.Messages; namespace Bum.Survey.CRM.Plugin { public class SurveyTokenAIU : IPlugin { public void Execute(IServiceProvider serviceProvider) { var process = new SurveyTokenAIUProcess(serviceProvider); process.LoadEntity(); if (!process.ValidateEntityName("bf_surveytoken")) return; if (!process.ValidateMessage(MessageName.Create, MessageName.Update, MessageName.Delete)) return; process.Run(); } } class SurveyTokenAIUProcess : bf_PluginProcess { public override void Execute() { if (TargetEntity.Contains("regardingobjectid")) { Entity record = new Entity(); Entity EntityName = (Entity)executionContext.InputParameters["Target"]; if (EntityName.Attributes.Contains("subject")) EntityName.Attributes["subject"] = EntityName.GetAttributeValue<EntityReference>("regardingobjectid").Name; if (executionContext.MessageName == MessageName.Update) { crmService.Update(EntityName); } if (executionContext.MessageName == MessageName.Update) { record = crmService.Retrieve(TargetEntity.LogicalName, TargetEntity.Id, new ColumnSet("subject", "regardingobjectid")); } else { record = TargetEntity; } string uniq = ""; int uniqLength = 1024; if (record.Contains("regardingobjectid")) { uniq = record.GetAttributeValue<EntityReference>("regardingobjectid").Name; RetrieveEntityRequest rerq = new RetrieveEntityRequest { LogicalName = record.GetAttributeValue<EntityReference>("regardingobjectid").LogicalName, RetrieveAsIfPublished = true }; RetrieveEntityResponse rers = (RetrieveEntityResponse)crmService.Execute(rerq); uniq = rers.EntityMetadata.DisplayName.UserLocalizedLabel.Label + " " + "[" + uniq + "]"; } if (!record.Contains("subject") || record["subject"].ToString() != uniq) { uniq = string.Format("{0}", uniq.Length > uniqLength ? (uniq.Substring(0, uniqLength - 3) + "...") : uniq); record["subject"] = uniq; if (executionContext.MessageName == MessageName.Update) { crmService.Update(record); } } } if (executionContext.MessageName == MessageName.Create) { QueryExpression surveyz = new QueryExpression() { EntityName = "bf_survey", ColumnSet = new ColumnSet(true) }; surveyz.Criteria.AddCondition("bf_surveyid", ConditionOperator.Equal, TargetEntity.GetAttributeValue<EntityReference>("bf_surveytoken_survey").Id); List<Entity> surveylists = crmService.RetrieveMultiple(surveyz).Entities.ToList(); foreach (var surveylist in surveylists) { QueryExpression token = new QueryExpression() { EntityName = "bf_surveytoken", ColumnSet = new ColumnSet(true) }; token.Criteria.AddCondition("bf_surveytoken_survey", ConditionOperator.Equal, surveylist.Id); List<Entity> surveyTokens = crmService.RetrieveMultiple(token).Entities.ToList(); QueryExpression tokenstart = new QueryExpression() { EntityName = "bf_surveytoken", ColumnSet = new ColumnSet(true) }; tokenstart.Criteria.AddCondition("bf_surveytoken_survey", ConditionOperator.Equal, surveylist.Id); tokenstart.Criteria.AddCondition("bf_surveytoken_sts", ConditionOperator.Equal, 100000001); List<Entity> surveyStartTokens = crmService.RetrieveMultiple(tokenstart).Entities.ToList(); QueryExpression tokenfinish = new QueryExpression() { EntityName = "bf_surveytoken", ColumnSet = new ColumnSet(true) }; tokenfinish.Criteria.AddCondition("bf_surveytoken_survey", ConditionOperator.Equal, surveylist.Id); tokenfinish.Criteria.AddCondition("bf_surveytoken_sts", ConditionOperator.Equal, 100000002); List<Entity> surveyFinishTokens = crmService.RetrieveMultiple(tokenfinish).Entities.ToList(); surveylist["bf_survey_tkfin"] = surveyStartTokens.Count; surveylist["bf_survey_tkstart"] = surveyStartTokens.Count; surveylist["bf_survey_tkcnt"] = surveyTokens.Count + 1; crmService.Update(surveylist); } } if (executionContext.MessageName == MessageName.Delete) { QueryExpression surveyz = new QueryExpression() { EntityName = "bf_survey", ColumnSet = new ColumnSet(true) }; surveyz.Criteria.AddCondition("bf_surveyid", ConditionOperator.Equal, TargetEntity.GetAttributeValue<EntityReference>("bf_surveytoken_survey").Id); List<Entity> surveylists = crmService.RetrieveMultiple(surveyz).Entities.ToList(); foreach (var surveylist in surveylists) { QueryExpression token = new QueryExpression() { EntityName = "bf_surveytoken", ColumnSet = new ColumnSet(true) }; token.Criteria.AddCondition("bf_surveytoken_survey", ConditionOperator.Equal, surveylist.Id); List<Entity> surveyTokens = crmService.RetrieveMultiple(token).Entities.ToList(); surveylist["bf_survey_tkcnt"] = surveyTokens.Count - 1; crmService.Update(surveylist); } } } public SurveyTokenAIUProcess(IServiceProvider serviceProvider) : base(serviceProvider) { } } } |
|
23.04.2014, 17:43 | #10 |
Чайный пьяница
|
А код bf_PluginProcess? В конструкторе ведь наверняка TargetEntity заполяете...
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
23.04.2014, 17:46 | #11 |
Участник
|
Цитата:
X++: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xrm.Sdk.Messages; using Microsoft.Xrm.Sdk.Metadata; using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; namespace Bum.Survey.CRM.Plugin.BaseLib { public static class MessageName { public const string Create = "Create"; public const string Update = "Update"; public const string Delete = "Delete"; public const string RetrieveMultiple = "RetrieveMultiple"; public const string Retrieve = "Retrieve"; } public static class ParameterName { public const string Target = "Target"; public const string id = "id"; public const string Query = "Query"; public const string BusinessEntityCollection = "BusinessEntityCollection"; public const string BusinessEntity = "BusinessEntity"; } public class bf_PluginError : Exception { public bf_PluginError(string message) : base(message) { } } public abstract class bf_PluginProcess { IServiceProvider _serviceProvider; public IServiceProvider serviceProvider { get { return _serviceProvider; } } IPluginExecutionContext _executionContext; public IPluginExecutionContext executionContext { get { if (_executionContext == null) _executionContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); return _executionContext; } } IOrganizationServiceFactory _serviceFactory; public IOrganizationServiceFactory serviceFactory { get { if (_serviceFactory == null) _serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); return _serviceFactory; } } IOrganizationService _crmService; public IOrganizationService crmService { get { if (_crmService == null) _crmService = serviceFactory.CreateOrganizationService(executionContext.UserId); return _crmService; } } ITracingService _tracingService; public ITracingService tracingService { get { if (_tracingService == null) _tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); return _tracingService; } } public bf_PluginProcess(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } Entity _entity; public Entity TargetEntity { get { return _entity; } } EntityReference _entity_key; public EntityReference TargetKey { get { return _entity_key; } } public void LoadEntity() { if (executionContext.InputParameters.Contains(ParameterName.Target)) { if (executionContext.InputParameters[ParameterName.Target] is Entity) { _entity = (Entity)executionContext.InputParameters[ParameterName.Target]; _entity_key = new EntityReference(_entity.LogicalName, _entity.Id); } else if (executionContext.InputParameters[ParameterName.Target] is EntityReference) { _entity_key = (EntityReference)executionContext.InputParameters[ParameterName.Target]; } } if (executionContext.MessageName == MessageName.Create) { if (executionContext.OutputParameters.Contains(ParameterName.id)) _entity_key.Id = (Guid)executionContext.OutputParameters[ParameterName.id]; } } public void RequeryTarget() { RequeryTarget(new ColumnSet(true)); } public void RequeryTarget(ColumnSet columnSet) { _entity = crmService.Retrieve(TargetKey.LogicalName, TargetKey.Id, columnSet); } public bool ValidateEntityName(string logicalName) { return _entity_key.LogicalName == logicalName; } public bool ValidateMessage(params string[] messages) { return messages.Contains(executionContext.MessageName); } abstract public void Execute(); public void Run() { try { Execute(); } catch (System.Exception ex) { throw new InvalidPluginExecutionException( String.Format("An error occurred in the {0} plug-in: {1}", this.GetType().ToString(), ex.ToString()), ex); } } public Dictionary<int, string> GetOptionSet(string entityName, string optionSetName) { RetrieveAttributeRequest req = new RetrieveAttributeRequest(); req.EntityLogicalName = entityName; req.LogicalName = optionSetName; RetrieveAttributeResponse res = (RetrieveAttributeResponse)_crmService.Execute(req); Dictionary<int, string> result = new Dictionary<int, string>(); foreach (var r in ((PicklistAttributeMetadata)res.AttributeMetadata).OptionSet.Options) { result.Add(r.Value.Value, r.Label.UserLocalizedLabel.Label); } return result; } } public static class DateTimeExt { public static string ConvertToCulturalString(this DateTime dt) { return dt.ToLocalTime().ToString("dd.MM.yyyy"); } } } |
|
23.04.2014, 18:08 | #12 |
Чайный пьяница
|
Мда. Зачем таким образом плагины писать - мне умом не понять (хотя я в CRM пришёл из мира ООП и немного в этом понимаю), но то ваше дело.
Суть в чём - как я и писал у вас не заполняется _entity. И соответственно проперти TargetEntity отдаёт null. Отсюда и ошибка. А вообще - учитесь дебажить плагины через VS.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
|
За это сообщение автора поблагодарили: Lavdislav (1). |
24.04.2014, 10:25 | #13 |
Участник
|
Цитата:
Сообщение от a33ik
Мда. Зачем таким образом плагины писать - мне умом не понять (хотя я в CRM пришёл из мира ООП и немного в этом понимаю), но то ваше дело.
Суть в чём - как я и писал у вас не заполняется _entity. И соответственно проперти TargetEntity отдаёт null. Отсюда и ошибка. А вообще - учитесь дебажить плагины через VS. |
|
24.04.2014, 10:54 | #14 |
Участник
|
Цитата:
Сообщение от a33ik
Мда. Зачем таким образом плагины писать - мне умом не понять (хотя я в CRM пришёл из мира ООП и немного в этом понимаю), но то ваше дело.
Суть в чём - как я и писал у вас не заполняется _entity. И соответственно проперти TargetEntity отдаёт null. Отсюда и ошибка. А вообще - учитесь дебажить плагины через VS. X++: if (executionContext.MessageName == MessageName.Delete) { if (executionContext.PreEntityImages.Contains("Target") && executionContext.PreEntityImages["Target"] is Entity) { Entity preMessageImage = (Entity)executionContext.PreEntityImages["Target"]; QueryExpression surveyz = new QueryExpression() { EntityName = "bf_survey", ColumnSet = new ColumnSet(true) }; surveyz.Criteria.AddCondition("bf_surveyid", ConditionOperator.Equal, preMessageImage.GetAttributeValue<EntityReference>("bf_surveytoken_survey").Id); List<Entity> surveylists = crmService.RetrieveMultiple(surveyz).Entities.ToList(); foreach (var surveylist in surveylists) { QueryExpression token = new QueryExpression() { EntityName = "bf_surveytoken", ColumnSet = new ColumnSet(true) }; token.Criteria.AddCondition("bf_surveytoken_survey", ConditionOperator.Equal, surveylist.Id); List<Entity> surveyTokens = crmService.RetrieveMultiple(token).Entities.ToList(); surveylist["bf_survey_tkcnt"] = surveyTokens.Count - 1; crmService.Update(surveylist); } } } |
|
24.04.2014, 11:01 | #15 |
Чайный пьяница
|
Повторюсь. Учитесь отлаживать плагины.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
24.04.2014, 11:46 | #16 |
Участник
|
|
|
|
|