共用方式為


擷取並偵測到中繼資料的變更

 

發行︰ 2017年1月

適用於: Dynamics 365 (online)、Dynamics 365 (on-premises)、Dynamics CRM 2016、Dynamics CRM Online

Microsoft.Xrm.Sdk.Metadata.Query 命名空間的類別以及 RetrieveMetadataChangesRequestRetrieveMetadataChangesResponse 類別讓您建立有效的中繼資料查詢並在變更持續發生時擷取變更至中繼資料。

在本文件中參照的程式碼範例文件可以在 範例:查詢中繼資料並偵測變更 中找到。

技術文章 使用 JavaScript 查詢中繼資料 提供 JavaScript 程式庫使用物件和用戶端備份碼的訊息。

本主題內容

使用中繼資料的策略

只擷取您需要的中繼資料

取得新的或變更後的中繼資料

取得關於已刪除中繼資料的資訊

使用中繼資料的策略

中繼資料在 Microsoft Dynamics 365 資料模型變更時,讓您能建立符合的應用程式。 中繼資料是下列類型應用程式所需:

  • 用戶端應用程式 UI

  • 整合工具必須對應 Dynamics 365 資料至外部系統

  • 開發工具

使用 Microsoft.Xrm.Sdk.Metadata.Query 命名空間的類別可以實作會顯示在一個輕量型查詢和無法變更中繼資料快取之間的設計。

輕量型查詢

輕量型查詢的範例,當您有自訂 Web 資源 UI 提供選取控制項,在 Microsoft Dynamics 365 選項組 (挑選清單) 屬性中顯示目前的選項。 您不會想要將這些選項寫死,因為您會需要更新此代碼 (可用選項變更的情況下)。 您可建構查詢來中繼資料中擷取這些選項值和索引標籤。

您不需要快取此資料,因為您可以使用 Microsoft.Xrm.Sdk.Metadata.Query 類別直接從 Microsoft Dynamics 365 應用程式快取擷取此資料。

持續中繼資料快取

當您的應用程式必須能夠在與 Microsoft Dynamics 365 伺服器中斷連線時運作,或是對於用戶端和伺服器之間有限的網路頻寬很敏感,例如行動應用程式,您會想要實作連續的中繼資料快取。

有了連續的中繼資料快取,您的應用程式在第一次連接時,需要查詢所有需要的中繼資料。 然後,你會在應用程式中儲存該資料。 下次應用程式連線道伺服器時,即可擷取與上次查詢相異的內容,如此應該會傳遞較少量的資料,且在您的應用程式載入時,合併變更至您的中繼資料快取。

輪詢中繼資料變更的頻率,應視應用程式中繼資料的變更程度,以及應用程式執行的時間來決定。 發生中繼資料變更時,不可使用偵測可用事件。 刪除中繼資料變更的儲存天數是有限制的,且變更請求發生且超過限制,則需要完整重新初始中繼資料快取。 如需詳細資訊,請參閱已刪除的過期中繼資料。

當未變更時,查詢應該快速回應,且不會傳輸資料。 不過,如果發生變更,尤其是遭刪除的中繼資料項目從快取中移除的話,此請求應該會多花一點時間才能完成。其他資訊:擷取已刪除中繼資料時的效能

只擷取您需要的中繼資料

中繼資料會經常在應用程式開始時擷取或同步,也可能影響應用程式載入的時間。 這在行動應用程式第一次擷取中繼資料時尤其明顯。 如果您需要建立一支效能良好的應用程式,只擷取您需要的中繼資料是非常重要的。

EntityQueryExpression 類別提供結構和 QueryExpression 一致、您用來建立複雜查詢的類別來擷取實體資料。 不像 RetrieveAllEntitiesRequestRetrieveEntityRequestRetrieveAttributeRequest、或RetrieveRelationshipRequest 類別,RetrieveMetadataChangesRequest 包含一個 Query 接受 EntityQueryExpression 執行個體的參數,您可以用該參數為資料指定特定準則之外,再回傳您需要的屬性。 您可以使用 RetrieveAllEntitiesRequest 來回傳一整組的中繼資料,您可以使用 RetrieveMetadataChangesRequest,或特定屬性的標籤。

定義篩選準則

EntityQueryExpression.Criteria 屬性接受一個 MetadataFilterExpression,它包含 MetadataConditionExpression 的集合物件,並允許依據其值來定義篩選實體屬性。 這些情況使用 MetadataConditionOperator,允許使用以下運算子 :

MetadataFilterExpression 也包含 LogicalOperator 來代表是否在評估狀況時套用 AndOr 邏輯。

並非所有的屬性都可以用來做為篩選準則。 唯一屬性代表簡單的資料類型、列舉、BooleanManagedPropertyAttributeRequiredLevelManagedProperty 類型可以用於 MetadataFilterExpression。 當 BooleanManagedPropertyAttributeRequiredLevelManagedProperty 受指定時,只會評估 Value 屬性。

下表列出無法用於 MetadataFilterExpressionEntityMetadata 屬性:

Attributes

Description

DisplayCollectionName

DisplayName

ManyToManyRelationships

ManyToOneRelationships

OneToManyRelationships

Privileges

下列範例示範 MetadataFilterExpression,它會回傳一組不相交、使用者擁有的實體 (不包含要排除的實體清單):



     // An array 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 isVisibileInMobileTrue = new MetadataConditionExpression("IsVisibleInMobile", MetadataConditionOperator.Equals, true);
     EntityFilter.Conditions.Add(isVisibileInMobileTrue);


' An array SchemaName values for non-intersect, user-owned entities that should not be returned.
                  Dim excludedEntities() As String =
                      {
                          "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.
Dim EntityFilter As 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))
Dim isVisibileInMobileTrue As New MetadataConditionExpression("IsVisibleInMobile", MetadataConditionOperator.Equals, True)
EntityFilter.Conditions.Add(isVisibileInMobileTrue)

指定您需要的屬性

Properties 屬性接受 MetadataPropertiesExpression。 您可以設定 MetadataPropertiesExpression.AllPropertiestrue,如果您想要回傳所有屬性或您可以提供自傳集合至 MetadataPropertiesExpression.PropertyNames 來定義您想要在結果中納入那些屬性。

回傳的強類型物件會包含,但是僅限您請求的項目才會有資料。 其他屬性會是空的,但有以下幾種例外:每個中繼資料的項目會包括 MetadataIdLogicalNameHasChanged 值 (如果因為該項目而存在的話)。 您向 Properties 請求時,不必指定他們。

如果您不使用受管理的程式碼與實際剖析從 XMLHttpRequest 傳回的 responseXML,會取得每個項目,但僅有您請求的才會包含資料。 以下 XML 顯示會傳回的連絡人實體中繼 xml 資料,當 IsVisibleInMobile 是唯一要求的屬性。

<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 屬性:ManyToManyRelationshipsManyToOneRelationships、或 OneToManyRelationships

下列範例會為請求的實體傳回 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" });

'A properties expression to limit the properties to be included with entities
Dim EntityProperties As New MetadataPropertiesExpression() With {.AllProperties = False}
EntityProperties.PropertyNames.AddRange(New String() { "Attributes" })

擷取屬性中繼資料

EntityQueryExpression.AttributeQuery 屬性接受 AttributeQueryExpression,它會定義 CriteriaProperties,為符合 EntityQueryExpressionCriteriaProperties 的實體傳回屬性。

下表列出的 AttributeMetadata 屬性無法用於 MetadataFilterExpression

Description

DisplayName

OptionSet

Targets

下列範例將限制屬性傳回,僅限擁有 OptionSet 以及僅會回傳 OptionSetAttributeType 屬性:


//A condition expresson 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");

'A condition expresson to return optionset attributes
                  Dim optionsetAttributeTypes() As 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
Dim AttributeFilter As New MetadataFilterExpression(LogicalOperator.Or)
AttributeFilter.Conditions.AddRange(optionsetAttributeTypes)

'A Properties expression to limit the properties to be included with attributes
Dim AttributeProperties As New MetadataPropertiesExpression() With {.AllProperties = False}
AttributeProperties.PropertyNames.Add("OptionSet")
AttributeProperties.PropertyNames.Add("AttributeType")

擷取關聯中繼資料

EntityQueryExpression.RelationshipQuery 屬性接受一個 RelationshipQueryExpression 以指定您要的實體關聯 CriteriaProperties,用於符合EntityQueryExpressionCriteriaProperties 的實體。

在您的準則中使用 RelationshipType 屬性來指定您是否想要回傳 ManyToMany 關係或 OneToMany 關係。

下表列出的關係中繼資料屬性無法用於 MetadataFilterExpression:

OneToManyRelationshipMetadata.AssociatedMenuConfiguration

OneToManyRelationshipMetadata.CascadeConfiguration

ManyToManyRelationshipMetadata.Entity1AssociatedMenuConfiguration

ManyToManyRelationshipMetadata.Entity2AssociatedMenuConfiguration

擷取索引標籤

最後,EntityQueryExpression.LabelQuery 屬性接受一個 LabelQueryExpression,它能讓您指定一個或多個整數 LCID 值,用來決定要回傳哪一個翻譯的標籤。您可以在地區設定識別碼 (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);

Private _userId As Guid
Private _languageCode As Integer

_userId = (CType(_service.Execute(New WhoAmIRequest()), WhoAmIResponse)).UserId
_languageCode = RetrieveUserUILanguageCode(_userId)

 Protected Function RetrieveUserUILanguageCode(ByVal userId As Guid) As Integer
  Dim userSettingsQuery As New QueryExpression("usersettings")
  userSettingsQuery.ColumnSet.AddColumns("uilanguageid", "systemuserid")
  userSettingsQuery.Criteria.AddCondition("systemuserid", ConditionOperator.Equal, userId)
  Dim userSettings As EntityCollection = _service.RetrieveMultiple(userSettingsQuery)
  If userSettings.Entities.Count > 0 Then
Return CInt(Fix(userSettings.Entities(0)("uilanguageid")))
  End If
  Return 0
 End Function


'A label query expression to limit the labels returned to only those for the user's preferred language
Dim labelQuery As New LabelQueryExpression()
labelQuery.FilterLanguages.Add(_languageCode)

取得新的或變更後的中繼資料

RetrieveMetadataChangesResponse 類別回傳強類型的 EntityMetadataCollection,它會包含請求的資料。RetrieveMetadataChangesResponse 類別也會提供一個 ServerVersionStamp 值,你可以在稍後的請求中將它傳遞至 RetrieveMetadataChangesRequest.ClientVersionStamp 屬性中。 在針對 ClientVersionStamp 屬性包含一個值時,僅有符合 EntityQueryExpression 的且在擷取後 ClientVersionStamp 變更的資料才會回傳。 對此唯一的例外是您的 EntityQueryExpression.Properties 包含 EntityMetadata.Privileges 時。 不論 ClientVersionStamp 權限,一律會回傳。 如此,您的應用程式可以決定在您上次查詢中繼資料後,是否發生您擔心的重要變更。 隨後您可以合併任何新或變更的中繼資料至您的連續中繼資料快取中,如此一來,您的應用程式就可以避免因為下載不需要的中繼資料,而發生的效能問題。

HasChanged 屬性提供了可偵測中繼資料項目中某個子元素發生變更的方式。 因為所有中繼資料會隨著包含其中的中繼資料項目一起回傳,當 OptionMetadata 標籤變更時,其中的 EntityMetadataAttributeMetadata、以及 OptionSetMetadata 屬性將會回傳。 不過,對那些包含中繼資料項目的 HasChanged 屬性來說,會顯示為 false。 僅 OptionMetadata.HasChanged 屬性為 true。

以下範例將透過定義一個 EntityQueryExpression 和使用一個設為 ClientVersionStamp null 的請求做為初始請求。


//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);

}

'An entity query expression to combine the filter expressions and property expressions for the query.
                  Dim entityQueryExpression_Renamed As New EntityQueryExpression() With
                      {
                          .Criteria = EntityFilter,
                          .Properties = EntityProperties,
                          .AttributeQuery = New AttributeQueryExpression() With
                                            {
                                                .Criteria = AttributeFilter,
                                                .Properties = AttributeProperties
                                            },
                          .LabelQuery = labelQuery
                      }

'Retrieve the metadata for the query without a ClientVersionStamp
                  Dim initialRequest As RetrieveMetadataChangesResponse =
                      getMetadataChanges(entityQueryExpression_Renamed, Nothing, DeletedMetadataFilters.OptionSet)

Protected Function getMetadataChanges(ByVal entityQueryExpression_Renamed As EntityQueryExpression,
                                      ByVal clientVersionStamp As String,
                                      ByVal deletedMetadataFilter As DeletedMetadataFilters) As RetrieveMetadataChangesResponse
    Dim retrieveMetadataChangesRequest_Renamed As New RetrieveMetadataChangesRequest() With
        {
            .Query = entityQueryExpression_Renamed,
            .ClientVersionStamp = clientVersionStamp,
            .DeletedMetadataFilters = deletedMetadataFilter
        }

    Return CType(_service.Execute(retrieveMetadataChangesRequest_Renamed), RetrieveMetadataChangesResponse)

End Function

取得關於已刪除中繼資料的資訊

ClientVersionStampDeletedMetadataFilters 屬性設定於 RetrieveMetadataChangesRequest 時,RetrieveMetadataChangesResponse.DeletedMetadata 屬性將會回傳一個 DeletedMetadataCollectionDeletedMetadataCollection 包含任何 EntityMetadataAttributeMetadata 或已經從系統中刪除一段時間的 RelationshipMetadataBase 物件的 MetadataId 值。 如需詳細資訊,請參閱已刪除的過期中繼資料。

使用 DeletedMetadataFilters 列舉搭配 RetrieveMetadataChangesRequest.DeletedMetadataFilters,將資訊限於您感興趣的中繼資料類型。DeletedMetadataFilters 列舉提供下列選項:

您也可以使用 DeletedMetadataFilters 列舉做為 RetrieveMetadataChangesResponse.DeletedMetadata 的關鍵,來篩選 RetrieveMetadataChangesResponse.DeletedMetadata 屬性中的 GUID 值。

在您設計中繼資料快取時,您將會針對每個項目使用 MetadataId,以辨識刪除的中繼資料並移除之。

已刪除的過期中繼資料

任何刪除的中繼資料,可以在一段時間內用 Organization.ExpireSubscriptionsInDays 值追蹤到。 根據預設,此值為 90 天。 如果 RetrieveMetadataChangesRequest.ClientVersionStamp 值所指的前一個中繼資料查詢是過期日之前,此服務將會顯示一個 ExpiredVersionStamp 錯誤 (0x80044352),當您擷取資料更新,而現存的中繼資料快取中,請您一定要嘗試抓出此錯誤,並準備使用次要請求傳送的結果 (不使用 ClientVersionStamp) 來重新初始化您的中繼資料快取。ExpiredVersionStamp 錯誤也會在伺服器中發生變更時傳遞,例如 ExpireSubscriptionsInDays 值得變更,會精確地影響追蹤已刪除的中繼資料。

下列範例傳遞 ClientVersionStamp 並捕捉 ExpiredVersionStamp。 如果抓到錯誤,快取會透過設定為 nullClientVersionStamp 重新傳遞新的請求來重新初始化。


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;
}

Protected Function updateOptionLabelList(ByVal entityQueryExpression_Renamed As EntityQueryExpression,
                                         ByVal clientVersionStamp As String) As String
    'Retrieve metadata changes and add them to the cache
    Dim updateResponse As RetrieveMetadataChangesResponse
    Try
        updateResponse = getMetadataChanges(entityQueryExpression_Renamed, clientVersionStamp, DeletedMetadataFilters.OptionSet)
        addOptionLabelsToCache(updateResponse.EntityMetadata, True)
        removeOptionLabelsFromCache(updateResponse.DeletedMetadata, True)

    Catch ex As FaultException(Of Microsoft.Xrm.Sdk.OrganizationServiceFault)
        ' Check for ErrorCodes.ExpiredVersionStamp (0x80044352)
        ' Will occur when the timestamp exceeds the Organization.ExpireSubscriptionsInDays value, which is 90 by default.
        'INSTANT VB TODO TASK: There is no VB equivalent to 'unchecked' in this context:
        If ex.Detail.ErrorCode = CInt(&amp;H80044352) Then
            'reinitialize cache
            _optionLabelList.Clear()

            updateResponse = getMetadataChanges(entityQueryExpression_Renamed, Nothing, DeletedMetadataFilters.OptionSet)
            'Add them to the cache and display the changes
            addOptionLabelsToCache(updateResponse.EntityMetadata, True)

        Else
            Throw ex
        End If

    End Try
    Return updateResponse.ServerVersionStamp
End Function

擷取已刪除中繼資料時的效能

刪除中繼資料項目後,會儲存在資料庫中,而非在 Microsoft Dynamics 365 中繼資料快取中。 雖然刪除中繼資料受限於 MetadataId 以及中繼資料項目類型,但存取資料庫是一種需要更多伺服器資源而非單純查詢變更的作業。

另請參閱

在伺服器上擴充 Microsoft Dynamics 365
離線使用 Microsoft Dynamics 365 服務
範例:查詢中繼資料並偵測變更
搭配使用組織服務與 Dynamics 365 中繼資料
自訂實體中繼資料
自訂實體屬性中繼資料
自訂實體關聯中繼資料
使用 JavaScript 查詢中繼資料

Microsoft Dynamics 365

© 2017 Microsoft. 著作權所有,並保留一切權利。 著作權