为什么我的CRM插件中的所有引用属性都为null?

时间:2014-01-20 06:42:16

标签: c# plugins dynamics-crm-2011 crm dynamics-crm-2013

我正在使用早期绑定在联系人实体上编写PostUpdate插件 不幸的是,所有应该代表1:x关系的属性都是空的 代码非常简单:
 * CRMcontext是通过CrmSvcUtil.exe生成的文件,
 * service是LocalPluginContext的IOrganizationService:

using ( var serviceContext = new CRMcontext(service) )
{
  // This works fine
  var contact = serviceContext.CreateQuery<Contact>().First(c => c.Id == context.PrimaryEntityId);

  // why is currency null after this line?! (and yes, it's set in the entity)
  var currency = contact.transactioncurrency_contact;
}

我按照此示例(最后一个代码段):http://msdn.microsoft.com/en-us/library/gg695791.aspx

感谢您的帮助!

编辑:

/// <summary>
/// N:1 transactioncurrency_contact
/// </summary>
[Microsoft.Xrm.Sdk.AttributeLogicalNameAttribute("transactioncurrencyid")]
[Microsoft.Xrm.Sdk.RelationshipSchemaNameAttribute("transactioncurrency_contact")]
public TransactionCurrency transactioncurrency_contact
{
    get
    {
        return this.GetRelatedEntity<TransactionCurrency>("transactioncurrency_contact", null);
    }
    set
    {
        this.OnPropertyChanging("transactioncurrency_contact");
        this.SetRelatedEntity<TransactionCurrency>("transactioncurrency_contact", null, value);
        this.OnPropertyChanged("transactioncurrency_contact");
    }
}

3 个答案:

答案 0 :(得分:2)

CRM不会自动加载相关的实体属性。您需要在每个延迟加载的属性上调用LoadProperty

并且LameCoder不正确,LINQ to CRM不会生成Fetch Xml,而是QueryExpressions,这就是为什么它仅限于QueryExpressions拥有的任何功能。

编辑1 - 为什么这不会像MSDN文章中的最后一个示例那样隐式地工作?

GetRelatedEntity方法定义如下:

protected virtual IEnumerable<TEntity> GetRelatedEntities<TEntity>(string relationshipSchemaName, EntityRole? primaryEntityRole) where TEntity : Entity
{
  if (string.IsNullOrWhiteSpace(relationshipSchemaName))
    throw new ArgumentNullException("relationshipSchemaName");
  Relationship key = new Relationship(relationshipSchemaName)
  {
    PrimaryEntityRole = primaryEntityRole
  };
  if (!this.RelatedEntities.Contains(key))
    return (IEnumerable<TEntity>) null;
  else
    return Enumerable.Cast<TEntity>((IEnumerable) this.RelatedEntities[key].Entities);
}

如果您的早期绑定实体继承自Entity,那么它所做的只是访问它自己的内部RelatedEntities集合。它无法访问服务器以加载相关属性。

如果您使用CodeGeneration.CodeCustomization生成早期绑定实体,它应该按照您列出的那样工作,因为它将继承自CrmEntity,它会为您加载关系,因为它会覆盖GetRelatedEntity method使用上下文为你获取它。

答案 1 :(得分:1)

我的理解是LINQ查询只是创建FetchXML,除非你特别要求,否则不会扩展关系。

您应该在LINQ查询中加入以获得所需的关系,但请注意,根据CRM 2013 SDK LINQ查询仅支持内部联接。因此,您将无法找回错过关系的记录。

如果您使用SVC Util生成具有SDK扩展程序集的早期绑定类型(可能难以在插件中使用),则扩展程序具有的Context可以在您访问该属性时自动扩展。有关详细信息,请参阅Microsoft.Xrm.Client.CrmOrganizationServiceContext类,如果尚未通过调用Attach,则需要将实体附加到上下文。请记住,这只是懒惰地对关系进行查询,因此在场景后面会有多个查询。

如果您想在一个查询中完成所有操作,并且需要LEFT连接,请尝试直接使用FetchXML。

编辑: 另请注意,在您指定的MSDN链接中,该示例试图显示相关实体如何为null,除非您调用LoadProperty。所以你可以简单地调用LoadProperty来加载你需要的东西。

答案 2 :(得分:0)

对于2016年的CRM更新,有些事情发生了变化。您现在应该像Daryl建议的那样使用LoadProperty方法。这会奏效。

我使用CodeGeneration.CodeCustomization来生成早期绑定实体,但不幸的是,CRM 2016 SDK似乎还没有所需的Microsoft.Xrm.Client.CodeGeneration.dll。因此,从2016年更新开始,这种方式不再适用。