Récupérer et détecter les modifications apportées aux métadonnées

 

Date de publication : novembre 2016

S’applique à : Dynamics CRM 2015

Les classes de l’espace de noms Microsoft.Xrm.Sdk.Metadata.Query et les classes RetrieveMetadataChangesRequest et RetrieveMetadataChangesResponse vous permettent de créer des requêtes de métadonnées efficaces et de collecter les modifications apportées aux métadonnées à mesure qu’elles se produisent dans le temps.

Tous les exemples de code référencés dans ce document se trouvent dans Exemple : Rechercher des métadonnées et détecter les modifications.

L’article technique Rechercher des métadonnées à l’aide de JavaScript fournit une bibliothèque JavaScript pour utiliser les objets et messages dans le code côté client.

Contenu de la rubrique

Stratégies d’utilisation des métadonnées

Récupérer uniquement les métadonnées nécessaires

Récupérer les métadonnées nouvelles ou modifiées

Récupérer les informations relatives aux métadonnées supprimées

Stratégies d’utilisation des métadonnées

Les métadonnées vous permettent de créer des applications qui s’adaptent au fil des modifications du modèle de données Microsoft Dynamics 365. Les métadonnées sont importantes pour les types d’application suivants :

  • Interface utilisateur des applications clientes

  • Outils d’intégration devant mapper les données CRM aux systèmes externes

  • Outils de développement

Les classes de l’espace de noms Microsoft.Xrm.Sdk.Metadata.Query vous permettent d’implémenter des conceptions qui existent quelque part entre une requête légère et un cache de métadonnées persistant.

Requête légère

Un exemple de requête légère est une interface utilisateur de ressource Web personnalisée qui fournit un contrôle de sélection pour afficher les options actuelles dans un attribut Groupe d’options Microsoft CRM (liste déroulante). Vous ne souhaitez pas coder en dur ces options, car vous devrez mettre à jour ce code si les options disponibles sont modifiées. À la place, vous pouvez créer une requête pour récupérer uniquement ces valeurs d’options et étiquettes à partir des métadonnées.

Il n’est pas nécessaire de mettre en cache ces données, car vous pouvez utiliser les classes Microsoft.Xrm.Sdk.Metadata.Query pour les récupérer directement à partir du cache d’application Microsoft CRM.

Cache de métadonnées persistant

Lorsque vous disposez d’une application qui doit pouvoir s’exécuter lorsqu’elle est déconnectée de Microsoft CRM Server, ou qui est sensible à une limitation de la bande passante réseau entre le client et le serveur, telle qu’une application mobile, vous pouvez implémenter un cache de métadonnées persistant.

Avec un cache de métadonnées persistant, votre application devra rechercher toutes les métadonnées nécessaires lors de sa première connexion. Vous enregistrez ensuite ces données dans l’application. La prochaine fois que l’application se connectera au serveur, vous pourrez récupérer uniquement la différence depuis la dernière requête, ce qui doit représenter beaucoup moins de données à transmettre, puis fusionner les modifications dans votre cache de métadonnées pendant le chargement de votre application.

La fréquence de recherche des modifications de métadonnées dépend de la volatilité attendue des métadonnées de votre application et de la durée d’exécution de votre application. Il n’existe aucun événement disponible vous permettant de détecter quand des modifications sont apportées aux métadonnées. La durée d’enregistrement des modifications de métadonnées supprimées est limitée et une demande de modifications qui se produit au-delà de cette limite nécessite une réinitialisation complète du cache des métadonnées. Pour plus d'informations, voir Expiration des métadonnées supprimées.

Si aucune modification n’est apportée, la requête doit répondre rapidement et aucune donnée ne sera retournée. Toutefois, si des modifications sont apportées, en particulier si des éléments de métadonnées supprimées doivent être supprimés de votre cache, vous pouvez vous attendre à ce que la requête mette un peu plus de temps à s’exécuter.Pour plus d'informations :Performances lors de la récupération des métadonnées supprimées

Récupérer uniquement les métadonnées nécessaires

Les métadonnées sont souvent récupérées ou synchronisées au démarrage d’une application et peuvent affecter le temps de chargement de l’application. Cela est particulièrement vrai pour les applications mobiles qui récupèrent des métadonnées pour la première fois. Récupérer uniquement les métadonnées nécessaires est très important pour créer une application qui s’exécute correctement.

La classe EntityQueryExpression fournit une structure cohérente avec la classe QueryExpression que vous utilisez pour créer des requêtes complexes pour récupérer les données d’entité. Contrairement aux classes RetrieveAllEntitiesRequest, RetrieveEntityRequest, RetrieveAttributeRequest ou RetrieveRelationshipRequest, RetrieveMetadataChangesRequest contient un paramètre Query qui accepte une instance EntityQueryExpression que vous pouvez utiliser pour définir des critères spécifiques pour les données à retourner, en plus des propriétés souhaitées. Vous pouvez utiliser RetrieveMetadataChangesRequest pour retourner l’ensemble complet de métadonnées que vous obtenez à l’aide de RetrieveAllEntitiesRequest, ou simplement une étiquette pour un attribut spécifique.

Spécifier vos critères de filtre

La propriété EntityQueryExpression.Criteria accepte MetadataFilterExpression qui contient une collection d’objets MetadataConditionExpression permettant de définir des conditions de filtrage des propriétés d’entité en fonction de leur valeur. Ces conditions utilisent MetadataConditionOperator qui autorise les opérateurs suivants :

MetadataFilterExpression contient également LogicalOperator pour déterminer s’il faut appliquer une logique And ou Or lorsque vous évaluez les conditions.

Certaines propriétés peuvent être utilisées comme critère de filtre. Seules les propriétés qui représentent des types de données simples, des énumérations, des types BooleanManagedProperty ou AttributeRequiredLevelManagedProperty peuvent être utilisées dans MetadataFilterExpression. Si BooleanManagedProperty ou AttributeRequiredLevelManagedProperty est spécifié, seule la propriété Value est évaluée.

Le tableau suivant répertorie les propriétés EntityMetadata qui ne peuvent pas être utilisées dans MetadataFilterExpression :

Attributes

Description

DisplayCollectionName

DisplayName

ManyToManyRelationships

ManyToOneRelationships

OneToManyRelationships

Privileges

L’exemple suivant illustre MetadataFilterExpression qui retourne un ensemble d’entités sans intersection appartenant à l’utilisateur non incluses dans une liste d’entités à exclure :



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

Spécifier les propriétés souhaitées

La propriété Properties accepte MetadataPropertiesExpression. Vous pouvez affecter à MetadataPropertiesExpression.AllProperties la valeur true si vous souhaitez retourner toutes les propriétés ou vous pouvez fournir une collection de chaînes à MetadataPropertiesExpression.PropertyNames pour définir les propriétés à inclure dans les résultats.

Les objets fortement tapés retournés incluront toutes les propriétés, mais seules celles que vous demandez contiendront des données. Toutes les propriétés auront une valeur null, à quelques exceptions près : chaque élément de métadonnées inclura les valeurs MetadataId,LogicalName et HasChanged si elles existent pour cet élément. Il n’est pas nécessaire de les spécifier dans les propriétés Properties que vous demandez.

Si vous n’utilisez pas du code géré et analysez réellement la valeur responseXML retournée de XMLHttpRequest, vous obtiendrez des éléments pour chaque propriété, mais seules celles que vous demandez contiendront des données. Le code XML suivant indique le code xml des métadonnées d’entité de contact qui sera retourné lorsque IsVisibleInMobile est la seule propriété demandée.

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

Dans une prochaine version, d’autres améliorations peuvent être obtenues en ne retournant pas les éléments avec des valeurs null pour les propriétés qui n’ont pas été demandées. Si vous écrivez du code pour analyser ce code XML, vous devez vous attendre à ce que le code XML retourné pour la même requête soit réduit au seul code XML suivant.

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

Les métadonnées sont retournées en l’état dans une structure hiérarchique à l’aide de RetrieveAllEntitiesRequest. Pour accéder à un attribut ou une relation spécifique, vous devez créer une requête qui retourne l’entité dont il fait partie. Si vous souhaitez récupérer des données concernant un attribut spécifique, vous devez inclure la propriété EntityMetadata.Attributes dans EntityQueryExpression.Properties. Pour que les relations d’entité soient retournées, vous devez inclure une ou plusieurs des propriétés suivantes EntityMetadata : ManyToManyRelationships, ManyToOneRelationships ou OneToManyRelationships.

L’exemple suivant retourne la propriété Attributes pour les entités demandées :


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

Récupérer les métadonnées d’attribut

La propriété EntityQueryExpression.AttributeQuery accepte AttributeQueryExpression qui définit Criteria et Properties pour les attributs à retourner pour les entités correspondant à EntityQueryExpressionCriteria et Properties.

Le tableau suivant répertorie les propriétés AttributeMetadata qui ne peuvent pas être utilisées dans MetadataFilterExpression

Description

DisplayName

OptionSet

Targets

L’exemple suivant limite les attributs retournés à ceux avec OptionSet et retourne uniquement les propriétés OptionSet et AttributeType pour ces attributs :


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

Récupérer les métadonnées de relation

La propriété EntityQueryExpression.RelationshipQuery accepte RelationshipQueryExpression pour spécifier la relation d’entité Criteria et Properties souhaitée pour les entités correspondant à EntityQueryExpressionCriteria et Properties.

Utilisez la propriété RelationshipType dans vos critères pour spécifier si vous souhaitez retourner les relations ManyToMany ou OneToMany.

Le tableau suivant répertorie les propriétés de métadonnées de relation qui ne peuvent pas être utilisées dans MetadataFilterExpression :

OneToManyRelationshipMetadata.AssociatedMenuConfiguration

OneToManyRelationshipMetadata.CascadeConfiguration

ManyToManyRelationshipMetadata.Entity1AssociatedMenuConfiguration

ManyToManyRelationshipMetadata.Entity2AssociatedMenuConfiguration

Récupérer les étiquettes

Enfin, la propriété EntityQueryExpression.LabelQuery accepte LabelQueryExpression qui vous permet de spécifier une ou plusieurs valeurs d’entier LCID pour déterminer les étiquettes localisées à retourner.Les valeurs d'ID de paramètres régionaux valides sont disponibles sur la page Tableau des ID de paramètres régionaux (LCID). Si une organisation a plusieurs modules linguistiques installés, les étiquettes pour toutes les langues sont retournées sauf si vous spécifiez LabelQuery.

L’exemple suivant définit LabelQueryExpression qui limite les étiquettes à celles représentant la langue par défaut des utilisateurs.


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)

Récupérer les métadonnées nouvelles ou modifiées

La classe RetrieveMetadataChangesResponse retourne un objet EntityMetadataCollection fortement tapé contenant les données demandées. La classe RetrieveMetadataChangesResponse fournit également une valeur ServerVersionStamp que vous pouvez passer à la propriété RetrieveMetadataChangesRequest.ClientVersionStamp dans les demandes ultérieures. Lorsqu’une valeur est incluse pour la propriété ClientVersionStamp, seules les données qui correspondent à EntityQueryExpression et qui ont été modifiées depuis la récupération de ClientVersionStamp sont retournées. La seule exception est lorsque votre EntityQueryExpression.Properties contient EntityMetadata.Privileges. Les privilèges sont toujours retournés indépendamment de ClientVersionStamp. Ainsi, votre application peut déterminer si des modifications importantes se sont produites depuis la dernière recherche de métadonnées. Vous pouvez ensuite fusionner les métadonnées nouvelles ou modifiées dans le cache de métadonnées persistant pour éviter que votre application rencontre des problèmes de performances liés au téléchargement de métadonnées inutiles.

La propriété HasChanged permet de détecter les éléments enfants modifiés dans un élément de métadonnées. Comme toutes les métadonnées sont retournées dans le cadre de l’élément de métadonnées conteneur, lorsque l’étiquette de OptionMetadata a été modifiée, les propriétés conteneurs EntityMetadata, AttributeMetadata et OptionSetMetadata sont retournées. Toutefois, la propriété HasChanged a la valeur false pour ces éléments de métadonnées conteneurs. Seule la propriété OptionMetadataHasChanged aura la valeur true.

L’exemple suivant effectue une demande initiale en définissant EntityQueryExpression et en effectuant une demande avec ClientVersionStamp défini sur la valeur 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

Récupérer les informations relatives aux métadonnées supprimées

La propriété RetrieveMetadataChangesResponse.DeletedMetadata retourne DeletedMetadataCollection lorsque les propriétés ClientVersionStamp et DeletedMetadataFilters sont définies sur RetrieveMetadataChangesRequest.DeletedMetadataCollection contient les valeurs MetadataId des objets EntityMetadata, AttributeMetadata ou RelationshipMetadataBase qui ont été supprimés du système dans un délai spécifique. Pour plus d'informations, voir Expiration des métadonnées supprimées.

Utilisez l’énumération DeletedMetadataFilters avec RetrieveMetadataChangesRequest.DeletedMetadataFilters pour limiter les informations aux types de métadonnées qui vous intéressent. L'énumération DeletedMetadataFilters fournit les options suivantes :

Vous utilisez également l’énumération DeletedMetadataFilters comme clé de RetrieveMetadataChangesResponse.DeletedMetadata pour filtrer les valeurs GUID contenues dans la propriété RetrieveMetadataChangesResponse.DeletedMetadata.

Lorsque vous concevez un cache de métadonnées, vous pouvez utiliser MetadataId pour chaque élément afin d’identifier les éléments de métadonnées supprimées et les supprimer.

Expiration des métadonnées supprimées

Les éléments de métadonnées supprimées sont suivis pour une période limitée spécifiée par la valeur Organization.ExpireSubscriptionsInDays. Par défaut, cette valeur est 90 jours. Si la valeur RetrieveMetadataChangesRequest.ClientVersionStamp indique que la dernière requête de métadonnées a été émise avant la date d’expiration, le service lève une erreur ExpiredVersionStamp (0x80044352). Lorsque vous récupérez les données à actualiser et le cache de métadonnées existant, vous devez toujours essayer d’intercepter cette erreur et être prêt à réinitialiser le cache des métadonnées avec les résultats d’une deuxième demande passée sans ClientVersionStamp. L’erreur ExpiredVersionStamp est également levée lorsque des modifications du serveur, telles que des modifications de la valeur ExpireSubscriptionsInDays, affectent le suivi des métadonnées supprimées.

L’exemple suivant transmet ClientVersionStamp et intercepte ExpiredVersionStamp. Si l’erreur est interceptée, le cache est réinitialisé en transmettant une nouvelle demande avec ClientVersionStamp défini sur 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

Performances lors de la récupération des métadonnées supprimées

Lorsqu’un élément de métadonnées est supprimé, il est enregistré dans la base de données, et pas dans le cache des métadonnées de Microsoft CRM. Bien que les métadonnées supprimées soient limitées à MetadataId et au type d’élément de métadonnées, l’accès à la base de données est une opération qui nécessite davantage de ressources du serveur qu’une simple recherche de modifications.

Voir aussi

Écrire des applications et des extensions de serveur
Utilisation hors connexion des services Microsoft Dynamics CRM 2015
Exemple : Rechercher des métadonnées et détecter les modifications
Étendre le modèle de métadonnées
Personnaliser les métadonnées d’entité
Personnaliser les métadonnées d’attribut d’entité
Personnaliser des métadonnées de relation d’entité
Rechercher des métadonnées à l’aide de JavaScript

© 2017 Microsoft. Tous droits réservés. Copyright