Why are all reference properties null in my CRM plugin?

纵然是瞬间 提交于 2019-12-10 14:54:54

问题


I'm writing a PostUpdate Plugin on the contact entity using early binding.
Unfortunately, all properties which should represent 1:x relations are null.
The code is pretty simple:
* CRMcontext is the generated file via CrmSvcUtil.exe,
* service is the IOrganizationService from LocalPluginContext:

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;
}

I followed this example (the last code snippet): http://msdn.microsoft.com/en-us/library/gg695791.aspx

Thanks for any help!

Edit:

/// <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");
    }
}

回答1:


CRM doesn't load the related entity properties automatically. You'll need to call LoadProperty on each property that is lazily loaded.

And LameCoder is incorrect, LINQ to CRM doesn't generate Fetch Xml, but QueryExpressions, which is why it is limited to whatever capability QueryExpressions possess.

Edit 1 - Why doesn't this work implicitly as the last example in the MSDN article states?

The GetRelatedEntity method is defined as so:

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);
}

If your early bound entity inherits from Entity, then only thing it is doing is accessing it's own internal RelatedEntities collection. It is doing nothing to access the server to load the related property.

If you use the CodeGeneration.CodeCustomization to generate the early bound entities it should work as you have listed, because it'll inherit from CrmEntity, which will load the relationships for you since it overrides the GetRelatedEntity method uses the context to fetch it for you.




回答2:


My understanding is that the LINQ query is just going to create FetchXML, which will not expand relationships unless you specifically request it.

You should do a join in your LINQ query to get the relationships you need, but be aware that according to the CRM 2013 SDK LINQ queries only support inner joins. So you won't be able to get back records that are missing the relationship.

If you use the SVC Util to generate your earlybound types with the SDK extensions assemblies (which may be difficult to use within a plugin) the Context that the extension has is capable of auto-expanding when you access the property. See the Microsoft.Xrm.Client.CrmOrganizationServiceContext class for details, you'd need to attach the entity to the context if it isn't already by calling Attach. Keep in mind that this is just going to do a query for the relationship lazily, so it'll be multiple queries behind the scene.

If you want it all in one query, and need a LEFT join, try using FetchXML directly.

Edit: Also notice that in the MSDN link you specified, the example is trying to show how the related entity is null unless you call LoadProperty. So you could just simply call LoadProperty to load what you need.




回答3:


For the 2016 update of CRM some things have changed. You should now use the LoadProperty method as Daryl suggested. This will work.

I used the CodeGeneration.CodeCustomization to generate the early bound entities, but it seems that the CRM 2016 SDK doesn't have the required Microsoft.Xrm.Client.CodeGeneration.dll anymore unfortunately. So this way doesn't work anymore as of the 2016 update.



来源:https://stackoverflow.com/questions/21227737/why-are-all-reference-properties-null-in-my-crm-plugin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!