Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieve related entities of each, using RetrieveMultipleRequest

I'm trying to retrieve a list of entities from CRM, but I'd like to get each one with the related entities. So far, I've the following code:

FilterExpression filterExpression = new FilterExpression();
ConditionExpression condition = new ConditionExpression(Constants.ModifiedOnAttribute, ConditionOperator.GreaterEqual, lastSync);
filterExpression.AddCondition(condition);

QueryExpression query = new QueryExpression()
{
     EntityName = entityName,
     ColumnSet = new ColumnSet(attributesMetadata.Select(att => att.Name).ToArray<string>()),
     Criteria = filterExpression,
     Distinct = false,
     NoLock = true
};

RetrieveMultipleRequest multipleRequest = new RetrieveMultipleRequest();
multipleRequest.Query = queryExpression;

RetrieveMultipleResponse response = (RetrieveMultipleResponse)proxy.Execute(multipleRequest);

In the variable response, I can see the EntityCollection attribute, but inside, Related entities always come empty.

Related entities count is 0

I'd like to know if it is possible to retrieve the set of a given entities, with the related entities, using RetrieveMultipleRequest, rather than go one by one using RetrieveRequest.

like image 845
Milton Avatar asked Dec 04 '12 19:12

Milton


People also ask

How do I retrieve multiple records from a plugin?

Retrieve Multiple Example: //Create a query expression specifying the link entity alias and the columns of the link entity that you want to return QueryExpression qe = new QueryExpression(); qe. EntityName = "account"; qe.

What is query expression in CRM?

QueryExpression is useful in scenarios where you want to return multiple entities that match a certain criteria. It lets you specify which fields you want to have returned (from the specified entity type or any related entity) as part of the query result in order to improve performance.


2 Answers

One approach to retreive related entities data - adding LinkEntities to your query. Example below will make you an idea how to make this:

LinkEntity linkEntity = new LinkEntity("email", "new_emails", "activityid", "new_relatedemail", JoinOperator.Inner);
linkEntity.Columns.AddColumn("versionnumber");
linkEntity.Columns.AddColumn("new_emailsid");
linkEntity.EntityAlias = "related";

query = new QueryExpression("email");
query.ColumnSet.AddColumn("activityid");
query.ColumnSet.AddColumn("versionnumber");
query.Criteria.AddCondition("modifiedon", ConditionOperator.NotNull);
query.LinkEntities.Add(linkEntity);

And then you can access attributes from related entities using EntityAlias you specified above:

foreach (Entity entity in entities.Entities)
{
    if ((long)(entity["related.versionnumber"] as AliasedValue).Value > 0)
    {
        stop = false;
    }
}
like image 72
SergeyS Avatar answered Oct 05 '22 23:10

SergeyS


The RetrieveMultipleRequest is for returning multiple instances of a particular type of entity. I have spent a year using the CRM SDK from C# and I have found no way of populating those related entity collections in a single query. This basically leaves you with two options:

  1. Use the AliasedValue as SergeyS recommends. Remember when querying 1:Many relationships, be aware that you could be returning multiple results for the same parent entity. This is what I use most of the time.

  2. Perform a second query for each relationship you want access to. You'll probably get better performance if you can use an IN statement in your second query, based on the results of the first, rather than performing a separate query for each result of the first.

Below is some pseudo code to show the difference.

var contacts = GetContacts();

// One Request to get the cars for the contacts
var cars = GetCarsWhereContactIdIn(contacts.Select( c => c.new_ContactId));

foreach(var c in contacts){
    c.new_Cars.AddRange(cars.where(car => car.new_contactId = c.ContactId));
}

// Verses
var contacts = GetContacts();

foreach(var c in contacts){
    // One Request for each contact
    c.new_Cars.AddRange(GetCarsForContact(c.ContactId));
}
like image 24
Daryl Avatar answered Oct 05 '22 23:10

Daryl