|
|
#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)
{
}
}
} |
|
|
|
|
#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). | |
|
|
#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);
|
|
|
|
|
#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); } } |
|
|
|
|
#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. Причина: Прикрепил ошибку |
|
|
|
|
#6 |
|
Чайный пьяница
|
А может ещё ошибку сюда прикрепите?
Но моя гипотеза в следующем - при удалении записи в Target приходит не Entity а EntityReference. Для получения значения поля из лукапа рекомендую использовать Pre-Image удаляемой записи.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
|
|
|
#7 |
|
Участник
|
|
|
|
|
|
#8 |
|
Чайный пьяница
|
Скорее всего я прав. Полный код плагина предоставьте, пожалуйста.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
|
|
|
#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)
{
}
}
} |
|
|
|
|
#10 |
|
Чайный пьяница
|
А код bf_PluginProcess? В конструкторе ведь наверняка TargetEntity заполяете...
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
|
|
|
#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");
}
}
} |
|
|
|
|
#12 |
|
Чайный пьяница
|
Мда. Зачем таким образом плагины писать - мне умом не понять (хотя я в CRM пришёл из мира ООП и немного в этом понимаю), но то ваше дело.
Суть в чём - как я и писал у вас не заполняется _entity. И соответственно проперти TargetEntity отдаёт null. Отсюда и ошибка. А вообще - учитесь дебажить плагины через VS.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
|
|
| За это сообщение автора поблагодарили: Lavdislav (1). | |
|
|
#13 |
|
Участник
|
Цитата:
Сообщение от a33ik
Мда. Зачем таким образом плагины писать - мне умом не понять (хотя я в CRM пришёл из мира ООП и немного в этом понимаю), но то ваше дело.
Суть в чём - как я и писал у вас не заполняется _entity. И соответственно проперти TargetEntity отдаёт null. Отсюда и ошибка. А вообще - учитесь дебажить плагины через VS. |
|
|
|
|
#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); } } } |
|
|
|
|
#15 |
|
Чайный пьяница
|
Повторюсь. Учитесь отлаживать плагины.
__________________
Эмо разработчик, сначала пишу код, потом плачу над его несовершенством. Подписывайтесь на мой блог, twitter и YouTube канал. Пользуйтесь моим Ultimate Workflow Toolkit |
|
|
|
|
#16 |
|
Участник
|
|
|
|
|
|
|