Condividi tramite


Recuperare e rilevare le modifiche apportate ai metadati

 

Data di pubblicazione: gennaio 2017

Si applica a: Dynamics 365 (online), Dynamics 365 (on-premises), Dynamics CRM 2016, Dynamics CRM Online

Le classi nello spazio dei nomi Microsoft.Xrm.Sdk.Metadata.Query e le classi RetrieveMetadataChangesResponse e RetrieveMetadataChangesRequest consentono di creare query di metadati efficienti e di acquisire le modifiche ai metadati quando si verificano nel tempo.

Tutti gli esempi di codice a cui viene fatto riferimento in questo documento sono disponibili in Esempio: eseguire una query sui metadati e rilevare le modifiche.

L'articolo tecnico Query di metadati utilizzando JavaScript offre una libreria JavaScript per l'utilizzo di oggetti e messaggi nel codice sul lato client.

In questo argomento

Strategie per l'utilizzo dei metadati

Recuperare solo i metadati necessari

Recuperare metadati nuovi o modificati

Recuperare le informazioni sui metadati eliminati

Strategie per l'utilizzo dei metadati

I metadati consentono di creare le applicazioni che si adatto in base alle modifiche del modello di dati di Microsoft Dynamics 365. I metadati sono importanti per i tipi seguenti di applicazioni:

  • Interfaccia utente per le applicazione client

  • Strumenti di integrazione che devono eseguire il mapping dei dati di Dynamics 365 con i sistemi esterni

  • Strumenti di sviluppo

Con l'utilizzo delle classi nello spazio dei nomi di Microsoft.Xrm.Sdk.Metadata.Query è possibile implementare le progettazioni che esisteranno tra una query ridotta e una cache dei metadati persistente.

Query ridotta

Ad esempio, si tratta di query ridotta quando si dispone di un'interfaccia utente della risorsa Web personalizzata che fornisce un controllo di selezione per visualizzare le opzioni correnti in un attributo (Picklist) del set di opzioni di Microsoft Dynamics 365. Non si desidera specificare tali opzioni come hard-coded poiché tale codice dovrebbe essere aggiornato se le opzioni disponibili vengono modificate. sul latoÈ invece possibile costruire una query per recuperare solo tali etichette e valori di opzioni dai metadati.

Non è necessario memorizzare nella cache questi dati poiché è possibile utilizzare le classi Microsoft.Xrm.Sdk.Metadata.Query per recuperare questi dati direttamente dalla cache dell'applicazione Microsoft Dynamics 365.

Cache dei metadati persistente

Quando disponi di un'applicazione che deve essere in grado di funzionare quando è disconnessa da Microsoft Dynamics 365 Server o che è sensibile alla larghezza di banda di rete limitata tra il client e il server, ad esempio un'applicazione mobile, potresti voler implementare una cache dei metadati persistente.

Con una cache dei metadati persistente l'applicazione dovrà eseguire una query su tutti i metadati necessari la prima volta che esegue la connessione. Quindi si salveranno tali dati nell'applicazione. Le volta successiva che l'applicazione si connette al server è possibile recuperare solo la differenza dall'ultima query, che dovrebbe risultare in molti meno dati da trasmettere e quindi unire le modifiche nella cache dei metadati quando l'applicazione si sta caricando.

La frequenza con cui è necessario eseguire il polling delle modifiche dei metadati dipende dalla volatilità prevista dei metadati per l'applicazione e dal periodo in cui l'applicazione resta in esecuzione. Non è disponibile un evento disponibile che è possibile utilizzare per rilevare quando si verificano le modifiche ai metadati. Esiste un limite al numero di giorni in cui vengono salvate le modifiche ai metadati eliminati e una richiesta di modifiche che si verifica oltre tale limite richiederà una nuova inizializzazione completa della cache dei metadati. Per ulteriori informazioni, vedere Scadenza di metadati eliminati.

Quando non esistono modifiche, la query deve rispondere rapidamente e non ci saranno dati da trasmettere nuovamente. Tuttavia, in caso di modifiche, in particolare se sono presenti elementi di metadati eliminati che devono essere rimossi dalla cache, è possibile prevedere che la richiesta possa richiedere altro tempo per essere completata.Ulteriori informazioni:Prestazioni durante il recupero dei metadati eliminati

Recuperare solo i metadati necessari

I metadati vengono recuperati di frequente o sincronizzati quando un'applicazione viene avviata e possono influenzare il tempo richiesto per il caricamento dell'applicazione. Questo aspetto è particolarmente vero per le applicazioni mobili che recuperano i metadati per la prima volta. Il recupero solo dei metadati necessari è molto importante per creare un'applicazione funzionante.

La classe EntityQueryExpression offre una struttura coerente con la classe QueryExpression utilizzata per creare query complesse per recuperare i dati dell'entità. A differenza delle classi RetrieveAllEntitiesRequest, RetrieveEntityRequest, RetrieveAttributeRequest o RetrieveRelationshipRequest, la classe RetrieveMetadataChangesRequest contiene un parametro Query che accetta un'istanza di EntityQueryExpression che è possibile utilizzare per specificare criteri specifici per i dati da restituire oltre alle proprietà desiderate. È possibile utilizzare RetrieveMetadataChangesRequest per restituire il set completo di metadati che si ottengono utilizzando RetrieveAllEntitiesRequest o semplicemente un'etichetta per un attributo specifico.

Specifica i criteri di filtro

La proprietà EntityQueryExpression.Criteria accetta un oggetto MetadataFilterExpression che contiene una raccolta di oggetti MetadataConditionExpression che consentono la definizione delle condizioni per filtrare le proprietà delle entità in base al relativo valore. Tali condizioni utilizzano un oggetto MetadataConditionOperator che consente i seguenti operatori:

L'oggetto MetadataFilterExpression include anche un LogicalOperator per indicare se applicare la logica And o Or quando si valutano le condizioni.

Non tutte le proprietà possono essere utilizzate come criteri di filtro. Solo le proprietà che rappresentano i tipi di dati semplici, le enumerazioni, o i tipi BooleanManagedProperty o AttributeRequiredLevelManagedProperty possono essere utilizzate in MetadataFilterExpression. Quando viene specificato un oggetto BooleanManagedProperty o AttributeRequiredLevelManagedProperty, viene valutata solo la proprietà Value.

Nella tabella seguente sono elencate le proprietà EntityMetadata che non è possibile utilizzare in un oggetto MetadataFilterExpression:

Attributes

Description

DisplayCollectionName

DisplayName

ManyToManyRelationships

ManyToOneRelationships

OneToManyRelationships

Privileges

Nell'esempio seguente viene illustrato un oggetto MetadataFilterExpression che restituirà un set di entità non intersecato e di proprietà dell'utente non incluso in un elenco di entità da escludere:



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

Specificare le proprietà desiderate

La proprietà Properties accetta un oggetto MetadataPropertiesExpression. È possibile impostare MetadataPropertiesExpression.AllProperties su true se si desidera restituire tutte le proprietà oppure è possibile fornire una raccolta di stringhe all'oggetto MetadataPropertiesExpression.PropertyNames per definire le proprietà che si desidera includere nei risultati.

Gli oggetti fortemente tipizzati restituiti includeranno tutte le proprietà, ma solo quelle richieste avranno dati. Tutte le altre proprietà saranno null, con le seguenti poche eccezioni: ogni elemento dei metadati includerà i valori MetadataId ,LogicalName e HasChanged se esistono per tale elemento. Non è necessario specificarli nell'oggetto Properties richiesto.

Se non si utilizza il codice gestito e si sta effettivamente analizzando responseXML restituito da XMLHttpRequest si otterranno elementi per ogni proprietà ma solo quelli richiesti conterranno i dati. Il codice XML seguente illustra l'xml dei metadati di entità del contatto che verranno restituiti quando IsVisibleInMobile è l'unica proprietà richiesta.

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

In un rilascio futuro è possibile ottenere maggiore efficienza evitando la restituzione di elementi con valori null per le proprietà non necessarie. Se si scrive il codice per analizzare questo XML è possibile che il codice XML restituito per la stessa query potrebbe essere ridotto solo al seguente 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>

I metadati vengono restituiti in una struttura gerarchica proprio come accade in caso di utilizzo di RetrieveAllEntitiesRequest. Per accedere a un attributo o a una relazione specifici è necessario creare una query che restituisce l'entità di cui fanno parte. Se desideri recuperare i dati su un attributo specifico, devi includere la proprietà EntityMetadata.Attributes in EntityQueryExpression.Properties. Per le relazioni di entità da restituire, è necessario includere una o più delle seguenti proprietà di EntityMetadata: ManyToManyRelationships, ManyToOneRelationships o OneToManyRelationships.

Il seguente esempio restituirà la proprietà Attributes per le entità necessarie:


//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" })

Recuperare i metadati di attributo

La proprietà EntityQueryExpression.AttributeQuery accetta un oggetto AttributeQueryExpression che definisce Criteria e Properties per gli attributi da restituire per le entità corrispondenti a EntityQueryExpressionCriteria e Properties.

Nella tabella seguente vengono elencate le proprietà AttributeMetadata che non è possibile utilizzare in un oggetto MetadataFilterExpression

Description

DisplayName

OptionSet

Targets

Il seguente esempio limiterà gli attributi restituiti solo a quelli con un oggetto OptionSet e restituirà solo le proprietà OptionSet e AttributeType per tali attributi:


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

Recuperare i metadati della relazione

La proprietà EntityQueryExpression.RelationshipQuery accetta un oggetto RelationshipQueryExpression per specificare la relazione di entità Criteria e Properties per le entità che corrispondono a EntityQueryExpressionCriteria e Properties.

Utilizzare la proprietà RelationshipType nei criteri per specificare se si desidera restituire le relazioni ManyToMany o OneToMany.

Nella tabella seguente vengono elencate le proprietà dei metadati della relazione che non possono essere utilizzate in un oggetto MetadataFilterExpression:

OneToManyRelationshipMetadata.AssociatedMenuConfiguration

OneToManyRelationshipMetadata.CascadeConfiguration

ManyToManyRelationshipMetadata.Entity1AssociatedMenuConfiguration

ManyToManyRelationshipMetadata.Entity2AssociatedMenuConfiguration

Recuperare le etichette

Infine, la proprietà EntityQueryExpression.LabelQuery accetta un oggetto LabelQueryExpression che consente di specificare uno o più valori LCID interi per determinare quali etichette localizzate restituire.Valori LCID (ID impostazioni locali) validi sono disponibili alla pagina Grafico LCID (impostazioni ID locali). Se un'organizzazione ha più Language Pack installati, le etichette per tutte le lingue verranno restituite a meno che non venga specificato un oggetto LabelQuery.

Nel seguente esempio viene definito un oggetto LabelQueryExpression che limiterà le etichette solo a quelle che rappresentano la lingua preferita degli utenti.


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)

Recuperare metadati nuovi o modificati

La classe RetrieveMetadataChangesResponse restituisce un oggetto EntityMetadataCollection fortemente tipizzato che contiene i dati necessari. La classe RetrieveMetadataChangesResponse fornisce inoltre un valore di ServerVersionStamp che è possibile passare alla proprietà RetrieveMetadataChangesRequest.ClientVersionStamp nelle richieste successive. Quando un valore viene incluso nella proprietà ClientVersionStamp, verranno richiamati solo i dati che corrispondono a EntityQueryExpression e sono cambiati da quando è stato recuperato ClientVersionStamp. L'unica eccezione è quando EntityQueryExpression.Properties include EntityMetadata.Privileges. I privilegi verranno restituiti sempre indipendentemente dall'oggetto ClientVersionStamp. In questo modo l'applicazione può determinare se si sono verificate modifiche importanti dall'ultima volta che è stata eseguita una query nei metadati. È quindi possibile unire i metadati nuovi o modificati nella cache dei metadati persistente in modo che l'applicazione sarà in grado di evitare problemi di prestazioni con il download dei metadati non necessari.

La proprietà HasChanged offre un modo per rilevare gli elementi secondari in un elemento dei metadati che sono cambiati. Poiché tutti i metadati vengono restituiti come parte dell'elemento di metadati contenente, quando l'etichetta di un oggetto OptionMetadata è cambiata, vengono restituite le proprietà EntityMetadata, AttributeMetadata e OptionSetMetadata contenenti. Tuttavia, la proprietà HasChanged sarà false per quelle contenenti gli elementi di metadati. Solo la proprietà OptionMetadataHasChanged sarà true.

L'esempio seguente esegue una richiesta iniziale definendo un oggetto EntityQueryExpression ed eseguendo una richiesta con ClientVersionStamp impostato su 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

Recuperare le informazioni sui metadati eliminati

La proprietà RetrieveMetadataChangesResponse.DeletedMetadata restituirà un oggetto DeletedMetadataCollection quando le proprietà ClientVersionStamp e DeletedMetadataFilters sono impostate nell'oggetto RetrieveMetadataChangesRequest. L'oggetto DeletedMetadataCollection contiene i valori MetadataId di qualsiasi oggetto EntityMetadata, AttributeMetadata o RelationshipMetadataBase che viene eliminato dal sistema in un periodo di tempo. Per ulteriori informazioni, vedere Scadenza di metadati eliminati.

Utilizza l'enumerazione DeletedMetadataFilters con RetrieveMetadataChangesRequest.DeletedMetadataFilters per limitare le informazioni solo a quei tipi di metadati desiderati. L'enumerazione DeletedMetadataFilters fornisce le seguenti opzioni:

Verrà inoltre utilizzata l'enumerazione DeletedMetadataFilters come chiave all'oggetto RetrieveMetadataChangesResponse.DeletedMetadata per filtrare i valori GUID trovati nella proprietà RetrieveMetadataChangesResponse.DeletedMetadata.

Quando si progetta una cache dei metadati, si desidererà utilizzare l'oggetto MetadataId per ogni elemento in modo da poter identificare gli elementi di metadati eliminati e rimuoverli.

Scadenza di metadati eliminati

Tutti gli elementi dei metadati eliminati vengono registrati per un periodo di tempo limitato specificato dal valore Organization.ExpireSubscriptionsInDays. Per impostazione predefinita questo valore è 90 giorni. Se il valore RetrieveMetadataChangesRequest.ClientVersionStamp indica che l'ultima query di metadati risale a prima della data di scadenza, il servizio genererà un errore ExpiredVersionStamp (0x80044352). Quando si recuperano i dati per aggiornare una cache dei metadati esistenti, è sempre necessario rilevare questo errore ed essere preparati a reinizializzare la cache dei metadati con i risultati da una seconda richiesta passata senza un oggetto ClientVersionStamp. L'errore ExpiredVersionStamp viene inoltre generato quando le modifiche nel server, ad esempio le modifiche al valore di ExpireSubscriptionsInDays, interessano in modo accurato la registrazione dei metadati eliminati.

Il seguente esempio passa un oggetto ClientVersionStamp e rileva ExpiredVersionStamp. Se l'errore è rilevato, la cache viene reinizializzata passando in una nuova richiesta con l'oggetto ClientVersionStamp impostato su null.


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

Prestazioni durante il recupero dei metadati eliminati

Quando un elemento dei metadati viene eliminato, questo viene salvato nel database e non nella cache dei metadati di Microsoft Dynamics 365. Sebbene i metadati eliminati siano limitati solo a MetadataId e al tipo di elemento dei metadati, l'accesso al database è un'operazione che richiederà più risorse del server piuttosto che solo l'esecuzione di query per le modifiche.

Vedere anche

Estendere Microsoft Dynamics 365 nel server
L'utilizzo offline dei servizi di Microsoft Dynamics 365
Esempio: eseguire una query sui metadati e rilevare le modifiche
Utilizzare il servizio Organizzazione con i metadati di Dynamics 365
Personalizzare i metadati dell'entità
Personalizzare i metadati degli attributi di entità
Personalizzare i metadati delle relazioni di entità
Query di metadati utilizzando JavaScript

Microsoft Dynamics 365

© 2017 Microsoft. Tutti i diritti sono riservati. Copyright