为什么我的自定义实体插件中的更新未发生?

时间:2015-07-09 13:45:36

标签: plugins dynamics-crm dynamics-crm-2015

我正在为MS Dynamics CRM 2015编写一个自动编号插件。当需要生成新编号时,它可以创建机会。当前号码存储在另一个实体中,在创建机会时检索该实体,然后添加1.然后使用新号码更新自动号码实体(除非此时此功能不起作用) )。

此时检索到数字并添加1并正确使用机会。但是,由于在创建另一个商机时未发生对自动编号实体的更新,因此它与前一个商机的编号相同。

到目前为止,这是我的插件代码:

protected void ExecuteGenerateOpportunityAutoNumber(LocalPluginContext localContext)
{
    if (localContext == null)
    {
        throw new ArgumentNullException("localContext");
    }

    IPluginExecutionContext context = localContext.PluginExecutionContext;
    IOrganizationService service = localContext.OrganizationService;

    if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
    {
        Entity entity = (Entity)context.InputParameters["Target"];

        if (entity.LogicalName == OPPORTUNITY_ENTITY_NAME)
        {
            if (!entity.Attributes.Contains(OPPORTUNITY_REF_ID))
            {
                try
                {
                    string newId = RetrieveAndUpdateLastId(service);
                    entity.Attributes.Add(OPPORTUNITY_REF_ID, newId);
                }
                catch (FaultException ex)
                {
                    throw new InvalidPluginExecutionException("GenerateOpportunityAutoNumber plugin error: ", ex);
                    //tracingService.Trace("GenerateOpportunityAutoNumber plugin error: {0}", ex.Message);
                }
            }
        }
    }
}

RetrieveAndUpdateLastId方法代码如下:

private string RetrieveAndUpdateLastId(IOrganizationService service)
{
    lock (lastIdentifierLock)
    {
        string result = null;

        ColumnSet cols = new ColumnSet();
        cols.AddColumns(LAST_REF_LAST_VALUE, LAST_REF_PRIMARY_KEY);

        QueryExpression query = new QueryExpression();
        query.ColumnSet = cols;
        query.EntityName = LAST_REF_ENTITY_NAME;

        EntityCollection ec = service.RetrieveMultiple(query);

        if (ec.Entities.Count >= 1)
        {
            foreach (Entity identifier in ec.Entities)
            {
                if (identifier.Attributes.Contains(LAST_REF_LAST_VALUE))
                {
                    int? lastValue = identifier[LAST_REF_LAST_VALUE] as int?;
                    if (lastValue != null)
                    {
                        string newValue = (lastValue.Value + 1).ToString().PadLeft(7, '0');

                        result = String.Format("SN{0}", newValue); //This is clearly happening as I'm getting the next number back.

                        identifier[LAST_REF_LAST_VALUE] = lastValue.Value + 1;

                        //Tried this also:
                        //identifier.Attributes.Remove(LAST_REF_LAST_VALUE);
                        //identifier.Attributes.Add(LAST_REF_LAST_VALUE, lastValue.Value + 1);

                        service.Update(identifier); //This doesn't seem to be happening.
                        break;
                    }
                }
            }
        }
        return result;
    }
}

不会抛出任何错误,但不会更新自动编号。我已经检查了我正在运行它的用户,因为它还具有自动编号实体所需的更新权限。有什么想法吗?

更新

调试后我发现它丢失了Principal用户缺少prvWrite权限的错误。这可以解释为什么更新没有发生,但现在引发了另一个问题。我已将插件设置为以特定用户身份运行(具有正确权限的用户),但错误中“主要用户”的Guid是主叫用户。当我将其设置为使用特定用户时,为什么它会作为主叫用户运行?

更新2

我想我可能已经找到了这个问题,但想知道是否有其他人可以确认/更多地了解这个问题。似乎根据this,问题可能在于用户不在特定的AD组中,特别是

  

用户帐户(A)需要特权prvActOnBehalfOfAnotherUser,   它包含在Delegate角色中。

     

或者,仅对于Active Directory目录服务部署,   用户帐户(A)可以运行模拟代码   添加到Active Directory中的PrivUserGroup组。这个小组是   由Microsoft Dynamics CRM在安装和设置期间创建。用户   帐户(A)不必与许可的Microsoft关联   Dynamics CRM用户。但是,被冒充的用户(B)   必须是获得许可的Microsoft Dynamics CRM用户。

出于我的目的,我认为我正在尝试运行的用户需要在AD中的PrivUserGroup中(它不是),否则默认为主叫用户。

更新3

我已经找到了两个基本问题。第一个是如上所述,因为上下文总是作为调用用户运行。第二个是,当给予调用用户系统管理员权限或使用null参数创建IOrganizationService时,它仍然不会更新。但是,这看起来很奇怪,这两个场景在分析插件时可行。为什么会这样?

更新4

我似乎已经解决了这个问题,虽然我不确定(因此我还没有写出答案)。根据文档,我们添加了要模拟到PrivUserGroup中的用户。该插件现在有效。但是,我不明白为什么需要这样做。另外,在这种情况下这是最佳做法还是我做过一些永远不应该做的事情?

在相关的说明中,我在这次部署之前也注销了插件,所以我现在想知道这是否解决了这个问题。要确认我现在已经从AD中的PrivUserGroup中删除了用户,但这显然需要一些时间(不确定确切地说多长时间)。如果它仍然有效,那么看起来这实际上解决了它。您是否通常需要在重新部署插件之前取消注册插件以确保其有效?

更新5

好的,所以如果我的最后更新。我并没有将此标记为答案,因为我不是100%肯定,但似乎使用插件注册工具删除程序集可能已经完成了这一操作。从我读过的所有东西中你都不需要取消注册一个插件来重新部署,所以我的程序集可能会以某种方式损坏它并通过删除它并使用新程序集再次创建它来解决问题。不幸的是,我没有原始的程序集来测试。

1 个答案:

答案 0 :(得分:1)

我建议调试你的插件。以下文章包含一个视频,介绍如何使用插件调试器和插件注册工具调试插件 - http://blogs.msdn.com/b/devkeydet/archive/2015/02/17/debug-crm-online-plugins.aspx

已更新 如何为用户上下文和系统提供2个IOrganizationService实例:

  1. 打开Plugin.cs文件。
  2. 找到以下代码:

    internal IOrganizationService OrganizationService
    {
        get;
    
        private set;
    }
    
  3. 在以下代码后添加以下代码:

    internal IOrganizationService SystemOrganizationService
    {
        get;
    
        private set;
    }
    
  4. 查找以下代码:

        // Use the factory to generate the Organization Service.
        this.OrganizationService = factory.CreateOrganizationService(this.PluginExecutionContext.UserId);
    
  5. 在以下代码后添加以下代码:

    this.SystemOrganizationService = factory.CreateOrganizationService(null);

  6. 在需要更高级别权限的地方使用此IOrganizationService实例。