CRM 2011 SDK (v5.0.10) を使用して、ターゲットが設定されていないいくつかのルックアップ フィールドで問題が発生しました。このような場合に、参照されるエンティティを決定する最善の方法を誰かが決定するのを手伝ってくれることを願っています。
具体的には、次の呼び出しでエンティティ、属性、および関係のメタデータを取得しています。
var entityRequest = new RetrieveAllEntitiesRequest
{
RetrieveAsIfPublished = true,
EntityFilters = EntityFilters.Entity | EntityFilters.Attributes | EntityFilters.Relationships
};
var entityResponse = (RetrieveAllEntitiesResponse)_organizationService.Execute(entityRequest);
return entityResponse.EntityMetadata.ToList();
その後、その呼び出しから返された EntityMetadata オブジェクトを操作しながら、Attributes コレクションを調べ、LookupAttributeMetadata オブジェクトについては、LookupAttributeMetadata オブジェクトの Targets プロパティを使用して、ルックアップによって参照されるエンティティを特定しようとします。
ただし、LookupAttributeMetadata オブジェクトの Targets コレクションが空の場合もあります。たとえば、Campaign Activity (論理名: CampaignActivity) エンティティには、ルックアップ フィールドとして定義された Service フィールド (論理名: serviced) がありますが、LookupAttributeMetadata オブジェクトの Targets プロパティは空です。
エンティティの Web UI カスタマイズ画面を見て、サービス フィールドを開くと、タイプ セクションの下に、タイプ: ルックアップ、ターゲット レコード タイプ: アカウント、関係名: キャンペーンアクティビティ_アカウントが表示されます。
この情報はどこから来たのですか?
また、キャンペーン アクティビティまたはアカウント エンティティのいずれにも、「campaignactivity_account」という名前の関係はありません。
更新: Dynamics CRM 2011 Rollup 8 のストック インストールを実行しています (これは Rolloup 7 でも見ました)。この例で使用したフィールドはキャンペーン アクティビティですが、この問題には合計 14 のフィールドがあり、以下にリストされています。if (entityName=="rollupfield" && fieldName=="organizationid")...
私が使用しているエンティティとフィールドは実行時にユーザーによって選択され、私は選択しないため、コードに大量のロジックが含まれないようにするための一般的な解決策 (それぞれの 1 回限りの解決策とは対照的) を探しています。何を渡されるかは、必ずしも前もってわかりません。
- エンティティ: ロールアップ フィールド (rollupfield) フィールド: 組織 ID (organizationid)
- エンティティ: ロールアップ クエリ (goalrollupquery) フィールド: 所有ユーザー (owninguser)
- エンティティ: プロセス ログ (workflowlog) フィールド: 関連 (regardingobjectid)
- エンティティ: 保存されたビュー (userquery) フィールド: 親クエリ (parentqueryid)
- エンティティ: キャンペーン活動 (campaignactivity) フィールド: サービス (serviceid)
- エンティティ: メール検索 (emailsearch) フィールド: 親 (parentobjectid)
- エンティティ: タイム ゾーンの定義 (timezonedefinition) フィールド: 組織 (organizationid)
- エンティティ: キャンペーン レスポンス (campaignresponse) フィールド: サービス (serviceid)
- エンティティ: クイック キャンペーン (一括操作) フィールド: サービス (serviceid)
- エンティティ: フィールド権限 (fieldpermission) フィールド: 組織 ID (organizationid)
- エンティティ: タイム ゾーンのローカライズされた名前 (timezonelocalizedname) フィールド: 組織 (organizationid)
- エンティティ: タイム ゾーン規則 (timezonerule) フィールド: 組織 (organizationid)
- エンティティ: 監査 (監査) フィールド: レコード (objectid)
- Entity: Post (投稿) Field: AboutObjectId (regardingobjectid)
更新: 次のコンソール アプリを使用して問題を再現できます。
//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>";
}
}
}