5

我正在使用早期绑定在联系人实体上编写 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");
    }
}
4

3 回答 3

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,那么它唯一要做的就是访问它自己的内部相关实体集合。它没有做任何事情来访问服务器以加载相关属性。

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

于 2014-01-20T19:57:00.620 回答
1

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

您应该在 LINQ 查询中进行连接以获得所需的关系,但请注意,根据 CRM 2013 SDK LINQ 查询仅支持内部连接。因此,您将无法取回缺少关系的记录。

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

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

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

于 2014-01-20T19:50:50.613 回答
1

对于 CRM 的 2016 年更新,一些事情发生了变化。您现在应该按照 Daryl 的建议使用 LoadProperty 方法。这将起作用。

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

于 2016-02-26T07:34:15.397 回答