テーブル定義の変更の取得および検出
注意
エンティティとテーブルの違いがわかりませんか? Microsoft Dataverse で「開発者: 用語を理解する」を参照してください。
Microsoft.Xrm.Sdk.Metadata.Query 名前空間のクラスと RetrieveMetadataChangesRequest および RetrieveMetadataChangesResponse クラスで、有効なメタデータ クエリの構築と時間経過に伴って発生するメタデータへの変更の取得が可能です。
このドキュメントで参照されるすべてのコード例はクエリにあり、定義 (メタデータ) の変更を検出します。
定義を使用するための戦略
テーブル定義と列定義は、Microsoft Dataverse データ モデリングとして調整するアプリケーションを作成することができます。 定義は次の種類のアプリケーションで重要です。
クライアント アプリケーションの UI
外部システムに Dataverse データをマップする統合ツール
開発ツール
Microsoft.Xrm.Sdk.Metadata.Query 名前空間のクラスを使用して軽量のクエリと永続メタデータ キャッシュ間に存在する設計を実行できます。
軽量のクエリ
軽量クエリの例には、Dataverse 選択肢 (ピックリスト) 列の現在の選択を表示するための選択コントロールを提供するカスタム Web リソース UI がある場合が含まれます。 使用可能な選択が変更されると、コードを更新する必要があるため、これらの選択はハード コードにするのは好ましくありません。 その代わり、定義から、選択値とラベルを取得するクエリを作成できます。
Dataverse アプリケーション キャッシュからこのデータを直接取得する場合に、Microsoft.Xrm.Sdk.Metadata.Query クラスを使用できるため、このデータをキャッシュする必要はありません。
永続定義 (メタデータ) キャッシュ
Dataverse サーバーから切断しているときに動作可能でなければならないアプリケーションがある場合や、モバイル アプリケーションなどのクライアントとサーバー間のネットワーク帯域幅の制限に影響を受けやすいアプリケーションがある場合、永続メタデータ キャッシュを実装することができます。
永続メタデータ キャッシュを使用すると、アプリケーションで最初の接続時に、必要なすべてのメタデータをクエリする必要があります。 次にそのアプリケーションにそのデータを保存します。 次にアプリケーションが接続する時には、最後のクエリからの差異のみを取得できます。これにより、送信する必要があるデータが少なくなり、アプリケーションを読み込んでいる間に、変更をメタデータ キャッシュに統合します。
メタデータの変更へのポーリング頻度は、アプリケーションのメタデータの変化予測と、アプリケーションの実行時間に基づいて決めます。 メタデータの変更がいつ発生するかの検出に使用できるイベントはありません。 検出されたメタデータの変更が保存される日数には制限があります。また、素の制限を超えて発生する変更要求があった場合、メタデータ キャッシュの完全再初期化が必要です。 詳細については、「削除されたメタデータの有効期限」を参照してください。
変更がない場合は、クエリはすぐに応答し、送信されるデータはありません。 ただし、特にキャッシュから削除される予定の削除済みメタデータ アイテムがある場合、その要求が終了するまでさらに時間がかかることが予想されます。 詳細: 削除されたメタデータを取得するときのパフォーマンス
必要な定義のみの取得
メタデータは、アプリケーションを起動した時に頻繁に取得または同期されるため、アプリケーションの読み込み時間に影響を与えます。 これは、メタデータを取得するのが初めてのモバイル アプリケーションで特に当てはまります。 必要なメタデータのみを取得することは、アプリケーションのパフォーマンスを向上させるために非常に重要です。
EntityQueryExpression クラスは、テーブル データを取得する複雑なクエリを作成するときに使用する QueryExpression クラスと構造的に一貫しています。 RetrieveAllEntitiesRequest、RetrieveEntityRequest、RetrieveAttributeRequest、または RetrieveRelationshipRequest クラスとは異なり、RetrieveMetadataChangesRequest には必要なプロパティに加えて返されるデータの特定の条件を指定するときに使用できる EntityQueryExpression インスタンスを受け入れる Query パラメーターが含まれます。 RetrieveMetadataChangesRequest を使用して、RetrieveAllEntitiesRequest を使用して取得したメタデータのフル セットまたは特定の属性のラベルだけを返すことができます。
フィルターの条件の指定
EntityQueryExpression.Criteria プロパティは、値に基づいてエンティティのプロパティをフィルター処理するための要件を定義できる MetadataConditionExpression オブジェクトのコレクションを含む MetadataFilterExpression を受け取ります。 これらの要件では、以下の演算子で使用できる MetadataConditionOperator を使用します。
MetadataConditionOperator.Equals
MetadataConditionOperator.NotEquals
MetadataConditionOperator.GreaterThan
MetadataConditionOperator.LessThan
MetadataFilterExpression には、条件の評価時に And または Or ロジックを適用するかどうかを表す LogicalOperator も含まれます。
一部のプロパティをフィルターの条件として使用できます。 シンプルなデータ型、列挙体、BooleanManagedProperty または AttributeRequiredLevelManagedProperty 型を表すプロパティのみを MetadataFilterExpression で使用できます。 BooleanManagedProperty または AttributeRequiredLevelManagedProperty を指定すると、Value プロパティだけが評価されます。
次の表は、MetadataFilterExpression で使用できない EntityMetadata プロパティを示します。
| プロパティ | プロパティ (続き) | プロパティ (続き) | プロパティ (続き) |
|---|---|---|---|
| Attributes | Description | DisplayCollectionName | DisplayName |
| ManyToManyRelationships | ManyToOneRelationships | OneToManyRelationships | Privileges |
次のコードは、除外するテーブルの一覧に含まれない、交差するテーブルではないユーザー所有のエンティティのセットを返す MetadataFilterExpression を示します。
// An array of SchemaName values for non-intersect, user-owned entities that should not be returned.
String[] excludedEntities = {
"WorkflowLog",
"Template",
"CustomerOpportunityRole",
"Import",
"UserQueryVisualization",
"UserEntityInstanceData",
"ImportLog",
"RecurrenceRule",
"QuoteClose",
"UserForm",
"SharePointDocumentLocation",
"Queue",
"DuplicateRule",
"OpportunityClose",
"Workflow",
"RecurringAppointmentMaster",
"CustomerRelationship",
"Annotation",
"SharePointSite",
"ImportData",
"ImportFile",
"OrderClose",
"Contract",
"BulkOperation",
"CampaignResponse",
"Connection",
"Report",
"CampaignActivity",
"UserEntityUISettings",
"IncidentResolution",
"GoalRollupQuery",
"MailMergeTemplate",
"Campaign",
"PostFollow",
"ImportMap",
"Goal",
"AsyncOperation",
"ProcessSession",
"UserQuery",
"ActivityPointer",
"List",
"ServiceAppointment"};
//A filter expression to limit entities returned to non-intersect, user-owned entities not found in the list of excluded entities.
MetadataFilterExpression EntityFilter = new MetadataFilterExpression(LogicalOperator.And);
EntityFilter.Conditions.Add(new MetadataConditionExpression("IsIntersect", MetadataConditionOperator.Equals, false));
EntityFilter.Conditions.Add(new MetadataConditionExpression("OwnershipType", MetadataConditionOperator.Equals, OwnershipTypes.UserOwned));
EntityFilter.Conditions.Add(new MetadataConditionExpression("SchemaName", MetadataConditionOperator.NotIn, excludedEntities));
MetadataConditionExpression isVisibleInMobileTrue = new MetadataConditionExpression("IsVisibleInMobile", MetadataConditionOperator.Equals, true);
EntityFilter.Conditions.Add(isVisibleInMobileTrue);
必要なプロパティの指定
Properties プロパティは MetadataPropertiesExpression を受け取ります。 すべてのプロパティを返す場合は MetadataPropertiesExpression.AllProperties を true に設定することができます。または文字列のコレクションを MetadataPropertiesExpression.PropertyNames に提供して 状態をどのプロパティに含めるかを定義することができます。
返される、厳密に型指定されたオブジェクトには、すべてのプロパティが含まれますが、要求したオブジェクトのみにデータがあります。 他のプロパティはすべて null ですが、いくつかの例外があります。メタデータの各アイテムはいずれも、そのアイテムの値が存在する場合は MetadataId、LogicalName および HasChanged の値が含まれます。 要求した Properties 内に指定する必要はありません。
マネージド コードを使用せず、XMLHttpRequest から返される responseXML を実際に分析する場合、各プロパティの要素が取得されますが、要求したものだけにデータが含まれます。 次の XML は IsVisibleInMobile が要求した唯一のプロパティの場合に返される、取引先担当者テーブル メタデータ XML を示します。
<a:EntityMetadata>
<c:MetadataId>608861bc-50a4-4c5f-a02c-21fe1943e2cf</c:MetadataId>
<c:HasChanged i:nil="true"/>
<c:ActivityTypeMask i:nil="true"/>
<c:Attributes i:nil="true"/>
<c:AutoRouteToOwnerQueue i:nil="true"/>
<c:CanBeInManyToMany i:nil="true"/>
<c:CanBePrimaryEntityInRelationship i:nil="true"/>
<c:CanBeRelatedEntityInRelationship i:nil="true"/>
<c:CanCreateAttributes i:nil="true"/>
<c:CanCreateCharts i:nil="true"/>
<c:CanCreateForms i:nil="true"/>
<c:CanCreateViews i:nil="true"/>
<c:CanModifyAdditionalSettings i:nil="true"/>
<c:CanTriggerWorkflow i:nil="true"/>
<c:Description i:nil="true"/>
<c:DisplayCollectionName i:nil="true"/>
<c:DisplayName i:nil="true"/>
<c:IconLargeName i:nil="true"/>
<c:IconMediumName i:nil="true"/>
<c:IconSmallName i:nil="true"/>
<c:IsActivity i:nil="true"/>
<c:IsActivityParty i:nil="true"/>
<c:IsAuditEnabled i:nil="true"/>
<c:IsAvailableOffline i:nil="true"/>
<c:IsChildEntity i:nil="true"/>
<c:IsConnectionsEnabled i:nil="true"/>
<c:IsCustomEntity i:nil="true"/>
<c:IsCustomizable i:nil="true"/>
<c:IsDocumentManagementEnabled i:nil="true"/>
<c:IsDuplicateDetectionEnabled i:nil="true"/>
<c:IsEnabledForCharts i:nil="true"/>
<c:IsImportable i:nil="true"/>
<c:IsIntersect i:nil="true"/>
<c:IsMailMergeEnabled i:nil="true"/>
<c:IsManaged i:nil="true"/>
<c:IsMappable i:nil="true"/>
<c:IsReadingPaneEnabled i:nil="true"/>
<c:IsRenameable i:nil="true"/>
<c:IsValidForAdvancedFind i:nil="true"/>
<c:IsValidForQueue i:nil="true"/>
<c:IsVisibleInMobile>
<a:CanBeChanged>false</a:CanBeChanged>
<a:ManagedPropertyLogicalName>canmodifymobilevisibility</a:ManagedPropertyLogicalName>
<a:Value>false</a:Value>
</c:IsVisibleInMobile>
<c:LogicalName>contact</c:LogicalName>
<c:ManyToManyRelationships i:nil="true"/>
<c:ManyToOneRelationships i:nil="true"/>
<c:ObjectTypeCode i:nil="true"/>
<c:OneToManyRelationships i:nil="true"/>
<c:OwnershipType i:nil="true"/>
<c:PrimaryIdAttribute i:nil="true"/>
<c:PrimaryNameAttribute i:nil="true"/>
<c:Privileges i:nil="true"/>
<c:RecurrenceBaseEntityLogicalName i:nil="true"/>
<c:ReportViewName i:nil="true"/>
<c:SchemaName i:nil="true"/>
</a:EntityMetadata>
将来のリリースでは、要求していないプロパティの値に null 要素を返さないようにすることでさらなる効率性が達成される可能性もあります。 この XML を解析するためのコードを作成する場合、同じクエリで返される XML を次の XML のみに削除することができることが想定されます。
<a:EntityMetadata>
<c:MetadataId>608861bc-50a4-4c5f-a02c-21fe1943e2cf</c:MetadataId>
<c:IsVisibleInMobile>
<a:CanBeChanged>false</a:CanBeChanged>
<a:ManagedPropertyLogicalName>canmodifymobilevisibility</a:ManagedPropertyLogicalName>
<a:Value>false</a:Value>
</c:IsVisibleInMobile>
<c:LogicalName>contact</c:LogicalName>
</a:EntityMetadata>
定義は階層構造で RetrieveAllEntitiesRequest を使用したときと同じように返されます。 特定の列または関係にアクセスするには、その一部となるテーブルを返すクエリを作成する必要があります。 特定の列についてのデータを取得する場合、EntityMetadata.Attributes を含める必要があります。 プロパティを EntityQueryExpression.Properties に含める必要があります。 返されるテーブル関係で、EntityMetadata プロパティの ManyToManyRelationships、ManyToOneRelationships、または OneToManyRelationships の 1 つまたは複数が含まれている必要があります。
次のコードは、要求したテーブルの Attributes プロパティを返します。
//A properties expression to limit the properties to be included with entities
MetadataPropertiesExpression EntityProperties = new MetadataPropertiesExpression()
{
AllProperties = false
};
EntityProperties.PropertyNames.AddRange(new string[] { "Attributes" });
列の定義を取得する
EntityQueryExpression.AttributeQuery プロパティは、EntityQueryExpressionCriteria および Properties に一致するテーブルに対して返される列の Criteria および Properties を定義する、AttributeQueryExpression を受入れます。
次の表は、MetadataFilterExpression で使用できない AttributeMetadata プロパティを示します。
| プロパティ | プロパティ (続き) |
|---|---|
| Description | DisplayName |
| OptionSet | Targets |
次の列は、返される列 (属性) を選択 (オプション セット) がある属性のみに制限し、これらの列に対し OptionSet および AttributeType プロパティのみを返します。
//A condition expression to return optionset attributes
MetadataConditionExpression[] optionsetAttributeTypes = new MetadataConditionExpression[] {
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.Picklist),
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.State),
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.Status),
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.Boolean)
};
//A filter expression to apply the optionsetAttributeTypes condition expression
MetadataFilterExpression AttributeFilter = new MetadataFilterExpression(LogicalOperator.Or);
AttributeFilter.Conditions.AddRange(optionsetAttributeTypes);
//A Properties expression to limit the properties to be included with attributes
MetadataPropertiesExpression AttributeProperties = new MetadataPropertiesExpression() { AllProperties = false };
AttributeProperties.PropertyNames.Add("OptionSet");
AttributeProperties.PropertyNames.Add("AttributeType");
関連付け定義の取得
EntityQueryExpression.RelationshipQuery プロパティは、EntityQueryExpressionCriteria および Properties と一致するテーブルに必要なエンティティの関連付け Criteria および Properties を指定する RelationshipQueryExpression を受入れます。
多対多の関連付けまたは一対多の関連付けを返すかどうかを指定するには、条件で RelationshipType プロパティを使用します。
次のテーブルは、MetadataFilterExpression で使用できない関連付けメタデータ プロパティを一覧表示します。
ラベルの取得
最後に、EntityQueryExpression.LabelQuery プロパティは、1 つまたは複数の整数 LCID 値を指定してどのローカライズされたラベルを返すかを決定できる LabelQueryExpression を受け取ります。 有効なロケール ID 値は、ロケール ID (LCID) の一覧のページで確認できます。 組織で複数の言語パックがインストールされている場合は、LabelQuery を指定しないとすべての言語が返されます。
次の例では、ユーザーが使用する言語を表すラベルのみに制限する LabelQueryExpression の定義を示します。
private Guid _userId;
private int _languageCode;
_userId = ((WhoAmIResponse)_service.Execute(new WhoAmIRequest())).UserId;
_languageCode = RetrieveUserUILanguageCode(_userId);
protected int RetrieveUserUILanguageCode(Guid userId)
{
QueryExpression userSettingsQuery = new QueryExpression("usersettings");
userSettingsQuery.ColumnSet.AddColumns("uilanguageid", "systemuserid");
userSettingsQuery.Criteria.AddCondition("systemuserid", ConditionOperator.Equal, userId);
EntityCollection userSettings = _service.RetrieveMultiple(userSettingsQuery);
if (userSettings.Entities.Count > 0)
{
return (int)userSettings.Entities[0]["uilanguageid"];
}
return 0;
}
//A label query expression to limit the labels returned to only those for the user's preferred language
LabelQueryExpression labelQuery = new LabelQueryExpression();
labelQuery.FilterLanguages.Add(_languageCode);
新規または変更済みの定義を取得する
RetrieveMetadataChangesResponse クラスは要求したデータが含まれている厳密に型指定された EntityMetadataCollection を返します。 RetrieveMetadataChangesResponse クラスは、以降の要求でRetrieveMetadataChangesRequest.ClientVersionStamp に渡すことができる ServerVersionStamp 値も含まれています。 値が ClientVersionStamp プロパティに含まれているとき、EntityQueryExpression に一致し、ClientVersionStamp が取得された以降に変更されたデータだけが返されます。 これの唯一の例外は、EntityQueryExpression.Properties が EntityMetadata.Privileges を含む場合です。 特権は ClientVersionStamp に関係なく、常に返されます。 こうすると、アプリケーションで最後にメタデータをクエリした後で関連する重要な変更が発生したかどうかを確認できます。 次に、新しいまたは変更されたメタデータを、アプリケーションで不要なメタデータのダウンロードに伴うパフォーマンスの問題が発生するのを防げるよう、永続メタデータ キャッシュに統合できます。
HasChanged プロパティでは、変更されたメタデータ アイテムの子要素を検出できる方法を提供します。 すべてのメタデータが、メタデータ アイテムの一部として返されるので、OptionMetadata のラベルを変更した場合、含まれる EntityMetadata、AttributeMetadata、OptionSetMetadata のプロパティが返されます。 ただし、HasChanged プロパティがこれらのメタデータ アイテムを含む場合は false を返します。 OptionMetadata.HasChanged プロパティのみが true になります。
次の例は EntityQueryExpression を定義し、null に設定されている ClientVersionStamp の要求を実行することにより、最初の要求を作成しています。
//An entity query expression to combine the filter expressions and property expressions for the query.
EntityQueryExpression entityQueryExpression = new EntityQueryExpression()
{
Criteria = EntityFilter,
Properties = EntityProperties,
AttributeQuery = new AttributeQueryExpression()
{
Criteria = AttributeFilter,
Properties = AttributeProperties
},
LabelQuery = labelQuery
};
//Retrieve the metadata for the query without a ClientVersionStamp
RetrieveMetadataChangesResponse initialRequest = getMetadataChanges(entityQueryExpression, null, DeletedMetadataFilters.OptionSet);
protected RetrieveMetadataChangesResponse getMetadataChanges(
EntityQueryExpression entityQueryExpression,
String clientVersionStamp,
DeletedMetadataFilters deletedMetadataFilter)
{
RetrieveMetadataChangesRequest retrieveMetadataChangesRequest = new RetrieveMetadataChangesRequest()
{
Query = entityQueryExpression,
ClientVersionStamp = clientVersionStamp,
DeletedMetadataFilters = deletedMetadataFilter
};
return (RetrieveMetadataChangesResponse)_service.Execute(retrieveMetadataChangesRequest);
}
削除された定義に関する情報の取得
RetrieveMetadataChangesResponse.DeletedMetadata プロパティは ClientVersionStamp および DeletedMetadataFilters プロパティが RetrieveMetadataChangesRequest に設定されている場合に DeletedMetadataCollection を返します。 DeletedMetadataCollection には、時間制限内で削除された EntityMetadata、AttributeMetadata または RelationshipMetadataBase オブジェクトの MetadataId の値を含みます。 詳細については、「削除されたメタデータの有効期限」を参照してください。
DeletedMetadataFilters 列挙を RetrieveMetadataChangesRequest.DeletedMetadataFilters とともに使用して、関心のあるメタデータの種類のみに情報を限定します。 DeletedMetadataFilters 列挙体には次のオプションが用意されています。
DeletedMetadataFilters.Entity (既定)
DeletedMetadataFilters.Attribute
DeletedMetadataFilters.Relationship
DeletedMetadataFilters.Label
DeletedMetadataFilters.OptionSet
また、DeletedMetadataFilters 列挙を RetrieveMetadataChangesResponse.DeletedMetadata へのキーとして使用し、RetrieveMetadataChangesResponse.DeletedMetadata で見つかった GUID の値をフィルター処理します。 プロパティ。
メタデータ キャッシュの設計を行う場合、削除されたメタデータ アイテムを識別して削除できるよう、アイテムごとに MetadataId を使用することができます。
定義の有効期限を削除しました
削除されたメタデータ アイテムは、Organization.ExpireSubscriptionsInDays の値により指定されている制限期間中、追跡されます。 既定では、値は 90 日に設定されています。 RetrieveMetadataChangesRequest.ClientVersionStamp 値が、最後のメタデータ クエリが有効期限の前のものであることを示している場合、サービスは ExpiredVersionStamp エラー (0x80044352) を表示します。データを取得して更新中に、既存のメタデータ キャッシュを取得しようとするたびにこのエラーが表示され、ClientVersionStamp を使用せずに渡された 2 番目の要求から結果を取得したメタデータ キャッシュの再初期化の準備が行われます。 ExpiredVersionStamp エラーは、ExpireSubscriptionsInDays 値の変更などのサーバー上での変更が、削除データの正確な追跡に影響する場合にもスローされます。
次の例は ClientVersionStamp を渡し、ExpiredVersionStamp を取得しています。 エラーが示された場合、キャッシュは null に設定された ClientVersionStamp を使用した新しい要求を渡すことによって再初期化されます。
protected String updateOptionLabelList(EntityQueryExpression entityQueryExpression, String clientVersionStamp)
{
//Retrieve metadata changes and add them to the cache
RetrieveMetadataChangesResponse updateResponse;
try
{
updateResponse = getMetadataChanges(entityQueryExpression, clientVersionStamp, DeletedMetadataFilters.OptionSet);
addOptionLabelsToCache(updateResponse.EntityMetadata, true);
removeOptionLabelsFromCache(updateResponse.DeletedMetadata, true);
}
catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> ex)
{
// Check for ErrorCodes.ExpiredVersionStamp (0x80044352)
// Will occur when the timestamp exceeds the Organization.ExpireSubscriptionsInDays value, which is 90 by default.
if (ex.Detail.ErrorCode == unchecked((int)0x80044352))
{
//reinitialize cache
_optionLabelList.Clear();
updateResponse = getMetadataChanges(entityQueryExpression, null, DeletedMetadataFilters.OptionSet);
//Add them to the cache and display the changes
addOptionLabelsToCache(updateResponse.EntityMetadata, true);
}
else
{
throw ex;
}
}
return updateResponse.ServerVersionStamp;
}
削除された定義を取得するときのパフォーマンス
メタデータ アイテムを削除すると、Dataverse メタデータ キャッシュではなくデータベースに保存されます。 削除されたメタデータが MetadataId とメタデータ アイテムの種類のみに制限されていても、データベースへのアクセスは変更をクエリするだけの場合よりもより多くのサーバー リソースが必要な操作です。
関連項目
拡張 Dynamics 365 Customer Engagement (on-premises)
Dynamics 365 サービスをオフラインで使用する
定義 (メタデータ) 変更のクエリと検出
メタデータと共に組織サービスを使用する
エンティティ メタデータのカスタマイズ
エンティティ属性メタデータのカスタマイズ
エンティティ関係メタデータをカスタマイズする
注意
ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)
この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。
フィードバック
フィードバックの送信と表示