CRM 2011 插件检查一个帐户是否有 parent
CRM 2011 plugin to check whether an Account has a parent
我正在用 C# 为 Dynamics CRM 2011 (On Prem) 编写插件。
该插件是为了防止帐户记录中出现祖父关系(帐户可以有 children 或 parent,但不能同时有两者)。
我正在努力检查帐户是否有关联的 parent,parent ID 的属性始终为空,我不明白为什么。
我已经使用 crmsvcutil.exe
正确生成了早期绑定 类 并将文件添加到我的项目中。
为 parent ID 生成的代码如下所示:
/// <summary>
/// Unique identifier of the parent account.
/// </summary>
[Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("parentaccountid")]
public Microsoft.Xrm.Sdk.EntityReference ParentAccountId
{
get
{
return this.GetAttributeValue<Microsoft.Xrm.Sdk.EntityReference>("parentaccountid");
}
set
{
this.OnPropertyChanging("ParentAccountId");
this.SetAttributeValue("parentaccountid", value);
this.OnPropertyChanged("ParentAccountId");
}
}
我的插件的基本版本如下所示:
namespace NoGrandparentAccounts
{
using CRM2011GeneratedBusinessModel; // Namespace for crmsvcutil generated early bound classes
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.ServiceModel;
public class Main : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// OBTAIN EXECUTION CONTEXT
var context(IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
// TRACING SERVICE FOR LOGGING
var tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));
// WILL REPRESENT THE CURRENT ENTITY
Entity entity = null;
// INPUTPARAMETERS COLLECTION CONTAINS ALL DATA PASSED IN THE MESSAGE REQUEST
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
// SET ENTITY TO THE CURRENT ENTITY
entity = (Entity)context.InputParameters["Target"];
// CHECK WE'RE IN ACCOUNTS ENTITY
if (context.PrimaryEntityName != "account")
return;
// CHECK WE'RE CREATING OR UPDATING THE ENTITY
if (context.MessageName != "Create" && context.MessageName != "Update")
return;
}
else
{
return;
}
try
{
// GET ORGANIZATION SERVICE
var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = serviceFactory.CreateOrganizationService(context.UserId);
// GET CURRENT ACCOUNT
var account = entity.ToEntity<Account>();
// HAS A PARENT ACCOUNT?
var hasParent = (account.ParentAccountId != null && account.ParentAccountId.Id != Guid.Empty);
}
catch (FaultException<OrganizationServiceFault> ex)
{
tracingService.Trace($@"Exception: {ex.Message} - {ex.StackTrace}");
throw new InvalidPluginExecutionException(@"An error occurred in the plugin.", ex);
}
catch (Exception ex)
{
tracingService.Trace($@"Exception: {ex.Message} - {ex.StackTrace}");
throw new InvalidPluginExecutionException(@"An error occurred in the plugin.", ex);
}
}
}
}
不幸的是,hasParent
始终为假,因为 account.ParentAccountId
为空。我不知道为什么,因为肯定有一个 parent 帐户与此记录相关联,属性名称肯定是 parentaccountid
.
查找 child 帐户的调用使用 parentaccountid
:
工作正常
// FETCH CHILDREN
var cExpr = new ConditionExpression("parentaccountid", ConditionOperator.Equal, account.Id);
var qExpr = new QueryExpression(Account.EntityLogicalName);
qExpr.ColumnSet = new ColumnSet(new string[] { "accountid" });
qExpr.Criteria.AddCondition(cExpr);
var results = service.RetrieveMultiple(qExpr);
// HAS CHILDREN
var hasChildren = results.Entities.Count > 0;
实体数正确显示为 3,因此 hasChildren
为真。
我检查了这个实体的属性是否包含 parentaccountid
并且它 returns false 我认为与问题有关:
if (entity.Attributes.Contains("parentaccountid"))
{
// Never gets here as this is false!?
}
我做错了什么?
Target 实体本身仅包含基本的实体标识数据。如果你想访问实体的属性,你应该使用你想要访问的属性配置一个合适的 PreImage 或 PostImage context.PreEntityImages,然后你可以通过 context.PreEntityImages
或 context.PostEntityImages
检索它。或者(不太理想)您可以从插件中检索具有所需属性的实体的最新版本。
这样做
// GET CURRENT ACCOUNT
var account = (Account)service.Retrieve("account", entity.Id, new ColumnSet(new string[] { "accountid", "parentaccountid" }));
而不是这个
// GET CURRENT ACCOUNT
var account = entity.ToEntity<Account>();
正如 Josh Painter 在他的评论中指出的那样,您注册的事件可能没有将此值传递给 PluginExecutionContext.InputParameters["Target"],因此当将实体转换为帐户。上面是如何进行查询以获取插件中的完整记录,并且它将始终被填充,除非插件是在创建前注册的(在这种情况下,您当前的代码可以正常工作,但是由于您正在一个空值,我假设你没有在前期创建时注册)。
我正在用 C# 为 Dynamics CRM 2011 (On Prem) 编写插件。
该插件是为了防止帐户记录中出现祖父关系(帐户可以有 children 或 parent,但不能同时有两者)。
我正在努力检查帐户是否有关联的 parent,parent ID 的属性始终为空,我不明白为什么。
我已经使用 crmsvcutil.exe
正确生成了早期绑定 类 并将文件添加到我的项目中。
为 parent ID 生成的代码如下所示:
/// <summary>
/// Unique identifier of the parent account.
/// </summary>
[Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("parentaccountid")]
public Microsoft.Xrm.Sdk.EntityReference ParentAccountId
{
get
{
return this.GetAttributeValue<Microsoft.Xrm.Sdk.EntityReference>("parentaccountid");
}
set
{
this.OnPropertyChanging("ParentAccountId");
this.SetAttributeValue("parentaccountid", value);
this.OnPropertyChanged("ParentAccountId");
}
}
我的插件的基本版本如下所示:
namespace NoGrandparentAccounts
{
using CRM2011GeneratedBusinessModel; // Namespace for crmsvcutil generated early bound classes
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.ServiceModel;
public class Main : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// OBTAIN EXECUTION CONTEXT
var context(IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
// TRACING SERVICE FOR LOGGING
var tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));
// WILL REPRESENT THE CURRENT ENTITY
Entity entity = null;
// INPUTPARAMETERS COLLECTION CONTAINS ALL DATA PASSED IN THE MESSAGE REQUEST
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
// SET ENTITY TO THE CURRENT ENTITY
entity = (Entity)context.InputParameters["Target"];
// CHECK WE'RE IN ACCOUNTS ENTITY
if (context.PrimaryEntityName != "account")
return;
// CHECK WE'RE CREATING OR UPDATING THE ENTITY
if (context.MessageName != "Create" && context.MessageName != "Update")
return;
}
else
{
return;
}
try
{
// GET ORGANIZATION SERVICE
var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = serviceFactory.CreateOrganizationService(context.UserId);
// GET CURRENT ACCOUNT
var account = entity.ToEntity<Account>();
// HAS A PARENT ACCOUNT?
var hasParent = (account.ParentAccountId != null && account.ParentAccountId.Id != Guid.Empty);
}
catch (FaultException<OrganizationServiceFault> ex)
{
tracingService.Trace($@"Exception: {ex.Message} - {ex.StackTrace}");
throw new InvalidPluginExecutionException(@"An error occurred in the plugin.", ex);
}
catch (Exception ex)
{
tracingService.Trace($@"Exception: {ex.Message} - {ex.StackTrace}");
throw new InvalidPluginExecutionException(@"An error occurred in the plugin.", ex);
}
}
}
}
不幸的是,hasParent
始终为假,因为 account.ParentAccountId
为空。我不知道为什么,因为肯定有一个 parent 帐户与此记录相关联,属性名称肯定是 parentaccountid
.
查找 child 帐户的调用使用 parentaccountid
:
// FETCH CHILDREN
var cExpr = new ConditionExpression("parentaccountid", ConditionOperator.Equal, account.Id);
var qExpr = new QueryExpression(Account.EntityLogicalName);
qExpr.ColumnSet = new ColumnSet(new string[] { "accountid" });
qExpr.Criteria.AddCondition(cExpr);
var results = service.RetrieveMultiple(qExpr);
// HAS CHILDREN
var hasChildren = results.Entities.Count > 0;
实体数正确显示为 3,因此 hasChildren
为真。
我检查了这个实体的属性是否包含 parentaccountid
并且它 returns false 我认为与问题有关:
if (entity.Attributes.Contains("parentaccountid"))
{
// Never gets here as this is false!?
}
我做错了什么?
Target 实体本身仅包含基本的实体标识数据。如果你想访问实体的属性,你应该使用你想要访问的属性配置一个合适的 PreImage 或 PostImage context.PreEntityImages,然后你可以通过 context.PreEntityImages
或 context.PostEntityImages
检索它。或者(不太理想)您可以从插件中检索具有所需属性的实体的最新版本。
这样做
// GET CURRENT ACCOUNT
var account = (Account)service.Retrieve("account", entity.Id, new ColumnSet(new string[] { "accountid", "parentaccountid" }));
而不是这个
// GET CURRENT ACCOUNT
var account = entity.ToEntity<Account>();
正如 Josh Painter 在他的评论中指出的那样,您注册的事件可能没有将此值传递给 PluginExecutionContext.InputParameters["Target"],因此当将实体转换为帐户。上面是如何进行查询以获取插件中的完整记录,并且它将始终被填充,除非插件是在创建前注册的(在这种情况下,您当前的代码可以正常工作,但是由于您正在一个空值,我假设你没有在前期创建时注册)。