Recuperare e rilevare le modifiche apportate ai metadati
Data di pubblicazione: novembre 2016
Si applica a: Dynamics CRM 2015
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 CRM 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 CRM. 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 CRM.
Cache dei metadati persistente
Quando si dispone di un'applicazione che deve essere in grado di funzionare quando è disconnessa dal server Microsoft CRM o che è sensibile alla larghezza di banda di rete limitata tra il client e il server, ad esempio un'applicazione mobile, è possibile che si desideri 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:
MetadataConditionOperator.Equals
MetadataConditionOperator.NotEquals
MetadataConditionOperator.GreaterThan
MetadataConditionOperator.LessThan
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:
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
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:
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:
DeletedMetadataFilters.Entity (predefinita)
DeletedMetadataFilters.Attribute
DeletedMetadataFilters.Relationship
DeletedMetadataFilters.Label
DeletedMetadataFilters.OptionSet
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(&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 CRM. 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
Scrivere applicazioni ed estensioni del server
Uso offline dei servizi di Microsoft Dynamics CRM 2015
Esempio: eseguire una query sui metadati e rilevare le modifiche
Estendere il modello dei metadati
Personalizzare i metadati dell'entità
Personalizzare i metadati degli attributi di entità
Personalizzare i metadati delle relazioni di entità
Query di metadati utilizzando JavaScript
© 2017 Microsoft. Tutti i diritti sono riservati. Copyright