Using the CRM 2011 SDK (v5.0.10) I'm running into an issue with a handful of Lookup fields where the target is not populated and am hoping someone can help me determine the best way to determine the referenced entity in these cases.
Specifically, I'm retrieving the Entity, Attribute and Relationship metadata with this call:
var entityRequest = new RetrieveAllEntitiesRequest
{
RetrieveAsIfPublished = true,
EntityFilters = EntityFilters.Entity | EntityFilters.Attributes | EntityFilters.Relationships
};
var entityResponse = (RetrieveAllEntitiesResponse)_organizationService.Execute(entityRequest);
return entityResponse.EntityMetadata.ToList();
Later, while working with an EntityMetadata object returned from that call, I inspect the Attributes collection and for LookupAttributeMetadata objects, I attempt to determine the entity referenced by the lookup using the Targets property of the LookupAttributeMetadata object.
However, there are some cases where a LookupAttributeMetadata object has an empty Targets collection. For example, the Campaign Activity (logical name: campaignactivity) entity has the Service field (logical name: serviced) defined as a Lookup field, but the Targets property on the LookupAttributeMetadata object is empty.
When I look at the web UI Customizations screen for the entity and open the Service field, under the Type section is shows Type: Lookup, Target Record Type: Account, Relationship Name: campaignactivity_account.
Where does this information come from?
Also note: there are no relationships named “campaignactivity_account” on either the Campaign Activity or Account entities.
Update:
I'm running a stock install of Dynamics CRM 2011 Rollup 8 (although I saw this on Rolloup 7 as well). While Campaign Activity is the field I used in my example, there are 14 total with this issue, listed below. I'm looking for a general solution (vs one-off solution for each) to keep from having a bunch of if (entityName=="rollupfield" && fieldName=="organizationid")...
logic in my code, since the entities and fields I'm working with are selected by the user at runtime and I don't necessarily know ahead of time what I'll be handed.
- Entity: Rollup Field (rollupfield) Field: Organization Id (organizationid)
- Entity: Rollup Query (goalrollupquery) Field: Owning User (owninguser)
- Entity: Process Log (workflowlog) Field: Regarding (regardingobjectid)
- Entity: Saved View (userquery) Field: Parent Query (parentqueryid)
- Entity: Campaign Activity (campaignactivity) Field: Service (serviceid)
- Entity: E-Mail Search (emailsearch) Field: Parent (parentobjectid)
- Entity: Time Zone Definition (timezonedefinition) Field: Organization (organizationid)
- Entity: Campaign Response (campaignresponse) Field: Service (serviceid)
- Entity: Quick Campaign (bulkoperation) Field: Service (serviceid)
- Entity: Field Permission (fieldpermission) Field: Organization Id (organizationid)
- Entity: Time Zone Localized Name (timezonelocalizedname) Field: Organization (organizationid)
- Entity: Time Zone Rule (timezonerule) Field: Organization (organizationid)
- Entity: Auditing (audit) Field: Record (objectid)
- Entity: Post (post) Field: RegardingObjectId (regardingobjectid)
Update: The following console app can be used to reproduce the issue.
//Requires the following Referenses:
// Microsoft.CSharp
// Microsoft.IdentityModel
// Microsoft.xrm.sdk
// System
// System.Core
// System.Data
// System.Runtime.Serialization
// System.ServiceModel
using System;
using System.Linq;
using System.Net;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;
namespace TargetlessLookupsPOC
{
internal static class Program
{
private const string OrganizationServiceURL =
"http://dynamicscrm1/DynamicsCRM1/XRMServices/2011/Organization.svc";
private static void Main(string[] args)
{
Console.WriteLine("====== Authenticating ");
var organizationServiceMngt =
ServiceConfigurationFactory.CreateManagement<IOrganizationService>(new Uri(OrganizationServiceURL));
var authCred = new AuthenticationCredentials();
authCred.ClientCredentials.Windows.ClientCredential = new NetworkCredential();
IOrganizationService orgProxy = new OrganizationServiceProxy(organizationServiceMngt,
authCred.ClientCredentials);
Console.WriteLine("====== Fetching All Entity Metadata ");
var entityRequest = new RetrieveAllEntitiesRequest
{
RetrieveAsIfPublished = true,
EntityFilters = EntityFilters.Entity | EntityFilters.Attributes | EntityFilters.Relationships
};
var entityResponse = (RetrieveAllEntitiesResponse) orgProxy.Execute(entityRequest);
Console.WriteLine("====== Searching For Targetless Lookups ");
foreach (var ent in entityResponse.EntityMetadata)
{
foreach (var field in ent.Attributes
.OfType<LookupAttributeMetadata>()
.Where(lookup => !lookup.Targets.Any()))
{
Console.WriteLine("Entity: {0} ({1}), Field: {2} ({3}) (type: {4}) is targetless",
ent.DisplayName.LabelText(), ent.LogicalName,
field.DisplayName.LabelText(), field.LogicalName,
field.AttributeType);
}
}
Console.WriteLine("=========================== Done");
Console.WriteLine("** Press any key to continue **");
Console.ReadKey();
}
public static string LabelText(this Label label)
{
return (label != null && label.UserLocalizedLabel != null)
? label.UserLocalizedLabel.Label
: "<no label>";
}
}
}
Appointment
and has a relationship name ofcampaignactivity_appointment
(which also does not exist). EDITED: I misread what was in my systemCampaignActivity_Appointments
exists but is not the same of course) – Greg Owens