I have the following code which works but I believe it is performing multiple look ups just to get the "Account" entity that is associated with my custom "Project" entity.
Is it possible to specify which associated entities you would like populated without having to loop through the initial result set?
public IList<new_project> GetAssociatedProjectsByPostcode(string postcode)
{
FilterExpression filter = new FilterExpression();
filter.FilterOperator = LogicalOperator.And;
filter.AddCondition(new ConditionExpression("new_project_zippostalcode", ConditionOperator.Equal, postcode));
QueryExpression query = new QueryExpression();
query.EntityName = new_project.EntityLogicalName;
query.ColumnSet = new ColumnSet(true);
query.Criteria = filter;
OrganizationServiceCache serviceCache = new OrganizationServiceCache(MemoryCache.Default, base.CrmConnection);
using (CachedOrganizationService service = new CachedOrganizationService(CrmConnection, serviceCache))
using (XrmServiceContext xrmServiceContext = new XrmServiceContext(service))
{
//Run the query to return the project entities in a list
IList<new_project> projects = service.RetrieveMultiple(query)
.Entities
.Select(item => item.ToEntity<new_project>())
.ToList<new_project>();
//Define the relationships we want populated
Relationship accountRel = new Relationship("new_account_new_project");
//We cannot call load property with tracking turned on
xrmServiceContext.MergeOption = MergeOption.NoTracking;
//Loop through the original list and get our associations
foreach (new_project np in projects)
xrmServiceContext.LoadProperty(np, accountRel);
return projects;
}
}
Is it possible to produce the equivalent with the ServiceContext?
Select Project.Name, Account.Name
From Project
Join Account ON Account.Id = Project.AccountId
EDIT :
After using the link entities as described by James below I now have the following which produces an entity collection with projects and accounts populated in one query but I cannot transfer this flat dataset into the hierarchical object structure.
public IList<new_project> GetAssociatedProjectsByPostcode(string postcode)
{
FilterExpression filter = new FilterExpression();
filter.FilterOperator = LogicalOperator.And;
filter.AddCondition(new ConditionExpression("new_project_zippostalcode", ConditionOperator.BeginsWith, PostcodeUtility.RegionFromPostcode(postcode)));
QueryExpression query = new QueryExpression();
query.EntityName = new_project.EntityLogicalName;
query.ColumnSet = new ColumnSet(true);
query.Criteria = filter;
query.LinkEntities.Add(new LinkEntity(new_project.EntityLogicalName, Account.EntityLogicalName, "new_associatedaccountid", "accountid", JoinOperator.Inner));
query.LinkEntities[0].Columns = new ColumnSet(true);
query.LinkEntities[0].EntityAlias = Account.EntityLogicalName;
OrganizationServiceCache serviceCache = new OrganizationServiceCache(MemoryCache.Default, base.CrmConnection);
using (CachedOrganizationService service = new CachedOrganizationService(CrmConnection, serviceCache))
using (XrmServiceContext xrmServiceContext = new XrmServiceContext(service))
{
EntityCollection ec = service.RetrieveMultiple(query);
//*****************************************************************
//The entity collection is now populated with the accounts but they
//are just additional key value pairs
//e.g. (String)((AliasedValue)ec[0]["account.name"]).Value;
//*****************************************************************
//Turn the entity collection into our class structure
IList<new_project> projects = ec.Entities
.Select(item => item.ToEntity<new_project>())
.ToList<new_project>();
return projects;
}
}