Share via


Conservation des données à long terme

La conservation des données à long terme automatise le transfert de données de votre base de données transactionnelle Microsoft Dataverse vers un lac de données géré pour un archivage rentable. Commencez par configurer des tables pour la conservation à long terme. Ensuite, créez des stratégies de conservation qui définissent les données à archiver. Les exécutions planifiées de la conservation transfèrent les lignes correspondant aux critères.

Important

Pour utiliser toutes les fonctionnalités de conservation des données à long terme, vous devez répondre aux deux exigences décrites ici : Vue d’ensemble de la conservation des données à long terme Dataverse.

Configurer une stratégie de conservation

Pour créer des stratégies de conservation, utilisez nos API, Maker Portal ou l’installation de la solution. L’exemple de code suivant illustre l’utilisation d’API pour créer une stratégie de conservation.

Le code suivant utilise le service d’organisation et la méthode IOrganizationService.Create(Entity) pour créer une stratégie de conservation qui conserve toutes les opportunités fermées et s’exécute chaque année. Les paramètres de périodicité valides sont DAILY, WEEKLY, MONTHLY et YEARLY. Pour exécuter la conservation une seule fois, définissez la valeur de périodicité sur Vide.

public void CreateRetentionConfig(IOrganizationService orgService)
{
    Entity retentionConfig = new Entity("retentionconfig");
    retentionConfig["retentionconfigid"] = Guid.NewGuid();
    retentionConfig["entitylogicalname"] = "incident";
    retentionConfig["name"] = "Retain all closed opportunities";
    retentionConfig["uniquename"] = "ui_RetainAllClosedOpportunities";
    retentionConfig["statecode"] = new OptionSetValue(0);
    retentionConfig["statuscode"] = new OptionSetValue(10);
    retentionConfig["criteria"] = "<fetch version=\"1.0\" output-format=\"xml-platform\" mapping=\"logical\" distinct=\"false\"> " +
        "<entity name=\"opportunity\"> " +
            "<attribute name=\"name\" /> " +
            "<attribute name=\"statecode\" />" +
            "<attribute name=\"actualvalue\" />" +
            "<attribute name=\"actualclosedate\" />" +
            "<attribute name=\"customerid\" />" +
            "<attribute name=\"opportunityid\" />" +
            "<order attribute=\"actualclosedate\" descending=\"true\" />" +
            "<filter type=\"and\">" +
                "<filter type=\"or\">" +
                    "<condition attribute=\"statecode\" operator=\"eq\" value=\"1\" />" +
                    "<condition attribute=\"statecode\" operator=\"eq\" value=\"2\" />" +
                "</filter>" +
            "</filter>" +
        "</entity></fetch>";
    retentionConfig["starttime"] = DateTime.Parse("2024-05-01T00:00:00");
    retentionConfig["recurrence"] = "FREQ=YEARLY;INTERVAL=1";
    try
    {
        var retentionConfigId = orgService.Create(retentionConfig);
        Console.WriteLine($"Retention policy created with Id : {retentionConfigId}");
    }
    catch (Exception ex)
    {
        throw new Exception($"Create retention policy failed: {ex.Message})", ex);
    }
}

Le résultat de ce code est « Stratégie de conservation créée avec ID : c1a9e932-89f6-4f17-859c-bd2101683263 ».

Valider votre stratégie de conservation

Le processus de conservation à long terme déplace les données du stockage transactionnel Dataverse vers un lac de données géré. Vous ne pouvez plus exécuter d’opérations transactionnelles sur les données une fois qu’elles sont déplacées vers le lac de données. Il est important de vous assurer que vos stratégies de conservation sont correctes. Vous pouvez ajouter vos propres validations en enregistrant éventuellement un plug-in sur le message ValidateRetentionConfig.

class SampleValidateRetentionConfigPlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        var pluginContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        var entityName = pluginContext.PrimaryEntityName;
        if( pluginContext.InputParameters.TryGetValue("FetchXml", out var fetchXml) )
        {
            // Add custom validation against the Fetch XML. 
        }
        else
        {
            throw new Exception("No critiera provided.");
        }
    }
}

Logique personnalisée pendant l’exécution de la conservation

La conservation à long terme est un processus asynchrone qui s’exécute chaque fois qu’une politique de rétention est configurée. Elle effectue les opérations suivantes :

  1. Marquer les lignes (enregistrements) prêtes pour la conservation.
  2. Copier les lignes marquées dans le lac de données.
  3. Vider les lignes de la base de données source.
  4. Restaurer les lignes marquées si le vidage échoue.

Vous pouvez éventuellement enregistrer des plug-ins personnalisés à exécuter lorsque les lignes sont marquées pour la conservation, lorsque les lignes sont vidées à la source ou lorsque les lignes marquées pour la conservation sont restaurées. L’écriture de code de plug-in s’applique uniquement au SDK pour la programmation .NET. L’API web ne prend pas en charge le développement de plug-ins.

Logique personnalisée lorsque la ligne est marquée pour rétention

Dans le cadre du marquage des lignes à conserver, Dataverse appelle les messages BulkRetain et Retain. Vous pouvez ajouter une logique personnalisée en enregistrant un plug-in lors de l’exécution de ces messages. Des exemples de logique personnalisée incluent de marquer plus de lignes pour la conservation ou d’exécuter une validation avant que les lignes ne soient marquées pour la conservation

Cet exemple de code montre un plug-in personnalisé exécuté lors de la conservation d’une seule ligne de table.

class SampleRetainPlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        var pluginContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        var entityName = pluginContext.PrimaryEntityName;
        if( pluginContext.InputParameters.TryGetValue("Target", out var _target) )
        {
            EntityReference target = (EntityReference)_target;
            Console.WriteLine($"Request came for table : {target.Name} with id : {target.Id}");
            // Add your logic for validation or additional operation. 
            // For example - you can call Retain on Additional row of another table. 
        }
        else
        {
            throw new Exception("No target present.");
        }
    }
}

Pour une opération de conservation de la restauration, écrivez votre plug-in de manière similaire à l’exemple ci-dessus, mais enregistrez-le dans le message RollbackRetain.

Logique personnalisée lors de la conservation en bloc

Cet exemple de code montre une logique personnalisée lors de l’exécution de la dernière page d’une opération de message BulkRetain

class SampleBulkRetainPlugin : IPlugin
{
    // Send notification when bulk retain execution is done. 
    public void Execute(IServiceProvider serviceProvider)
    {
        var pluginContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        var entityName = pluginContext.PrimaryEntityName;
        if(pluginContext.OutputParameters != null 
            && pluginContext.OutputParameters.TryGetValue("HasMoreRecords", out var _hasMoreRecords) )
        {    
            if(!(bool)_hasMoreRecords)
            {
                Console.WriteLine("This is a last execution of this request.");
                // SendNotifcation that retention for an entity is completed. 
            }
        }
    }
}

Logique personnalisée lorsqu’une ligne est supprimée en raison de la conservation

Dataverse exécute le message PurgeRetainedContent pour supprimer les lignes de données transactionnelles qui ont été déplacées avec succès vers le lac de données. Le message PurgeRetainedContent exécute en interne une opération de message Delete pour supprimer les lignes de la table qui ont été déplacées correctement

Vous pouvez enregistrer un plug-in personnalisé dans le message PurgeRetainedContent si une logique personnalisée est nécessaire lors de l’opération de vidage au niveau de la table. Vous pouvez éventuellement enregistrer un plug-in personnalisé dans le message Delete si vous devez appeler du code lorsqu’une ligne est supprimée en raison de la conservation. Vous pouvez déterminer si la suppression s’est produite en raison de la conservation ou non en vérifiant la propriété ParentContext du plug-in. La valeur de la propriété ParentContext pour l’opération de message Delete due à la conservation est « PurgeRetainedContent ».

Cet exemple de code bloque le vidage dans une table lorsque les lignes ne sont pas prêtes pour le vidage

class SamplePurgeRetainedContentPlugin : IPlugin
{
    // Block purge if all the rows are not validatd. 
    public void Execute(IServiceProvider serviceProvider)
    {
        var pluginContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        var entityName = pluginContext.PrimaryEntityName;
        if( pluginContext.InputParameters.TryGetValue("MaxVersionToPurge", out var _maxVersiontoPurge) )
        {
            long MaxVersionToPurge = (long)_maxVersiontoPurge;
            var rowsToBePurged = GetToBePurgedRows(entityName, MaxVersionToPurge);
            // Add custom validation to process rowsToBePurged.
        }
    }

    public EntityCollection GetToBePurgedRows(string  entityName, long maxVersionToPurge)
    {
        IOrganizationService organizationService; // Create OrgService. 
        QueryExpression queryExpression = new QueryExpression()
        {
            EntityName = entityName,
            ColumnSet = new ColumnSet(new string[] { "versionnumber", "msft_datastate" })
        };
        queryExpression.Criteria.AddCondition("msft_datastate", ConditionOperator.Equal, 1);
        queryExpression.Criteria.AddCondition("versionnumber", ConditionOperator.LessEqual, maxVersionToPurge);
        var response = organizationService.RetrieveMultiple(queryExpression);
        return response;
    }
}

Cet exemple de code s’applique à l’opération de suppression en raison de la conservation

class SampleDeletePlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        if (IsDeleteDueToRetention(serviceProvider))
        {
            // Write your code to handle delete during retention
        }
        else
        {
            // Write your code to handle normal delete without retention
        }
    }

    private bool IsDeleteDueToRetention(IServiceProvider serviceProvider)
    {
        var currentContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        while (currentContext != null)
        {
            if (string.Equals(currentContext.MessageName, "PurgeRetainedContent"))
            {
                return true;
            }
            else
            {
                currentContext = currentContext.ParentContext;
            }
        }
        return false;
    }
}

Stratégie de conservation des requêtes et détails d’exécution

Les détails de la stratégie de conservation sont stockés dans la table RetentionConfig. Les détails d’exécution de la conservation sont stockés dans les tables RetentionOperation et RetentionOperationDetail . Vous pouvez interroger ces tables pour obtenir la stratégie de conservation et les détails d’exécution.

Le code suivant fournit quelques exemples de FetchXML qui peuvent être utilisés pour interroger les lignes de la table des détails de conservation de la date. FetchXML est un langage de requête propriétaire basé sur XML. Il peut être utilisé avec des requêtes basées sur le SDK à l’aide de FetchExpression et par l’API web à l’aide de la chaîne de requête fetchXml

Cet exemple de code montre une requête simple pour renvoyer toutes les stratégies de conservation actives pour une commande par e-mail par nom.


public EntityCollection GetActivePolicies(IOrganizationService orgService)
{
    string fetchXml = @"
    <fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
      <entity name='retentionconfig'>
        <attribute name='retentionconfigid' />
        <attribute name='name' />
        <attribute name='createdon' />
        <attribute name='starttime' />
        <attribute name='recurrence' />
        <attribute name='entitylogicalname' />
        <attribute name='criteria' />
        <order attribute='name' descending='false' />
        <filter type='and'>
          <condition attribute='entitylogicalname' operator='eq' value='email' />
          <condition attribute='statuscode' operator='eq' value='10' />
        </filter>
      </entity>
    </fetch>";

    var query = new FetchExpression(fetchXml);

    EntityCollection results = orgService.RetrieveMultiple(query);

    results.Entities.ToList().ForEach(x => {
      Console.WriteLine(x.Attributes["name"]);
    });

    return(results);
}

Autres exemples de chaînes de requête FetchXML

Cet exemple de code illustre l’utilisation d’une instruction FetchXML pour récupérer toutes les stratégies de conservation suspendues pour un e-mail.

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
  <entity name="retentionconfig">
    <attribute name="retentionconfigid" />
    <attribute name="name" />
    <attribute name="createdon" />
    <attribute name="starttime" />
    <attribute name="recurrence" />
    <attribute name="entitylogicalname" />
    <attribute name="criteria" />
    <order attribute="name" descending="false" />
    <filter type="and">
      <condition attribute="entitylogicalname" operator="eq" value="email" />
      <condition attribute="statuscode" operator="eq" value="20" />
    </filter>
  </entity>
</fetch>

Cet exemple de code montre comment utiliser une instruction FetchXML pour récupérer toutes les opérations de conservation pour une stratégie de conservation.

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
  <entity name="retentionoperation">
    <attribute name="retentionoperationid" />
    <attribute name="name" />
    <attribute name="statuscode" />
    <attribute name="statecode" />
    <attribute name="starttime" />
    <attribute name="rootentitylogicalname" />
    <attribute name="endtime" />
    <attribute name="criteria" />
    <order attribute="name" descending="false" />
    <filter type="and">
      <condition attribute="retentionconfigid" operator="eq" uiname="All closed opportunities" uitype="retentionconfig" value="{35CC1317-20B7-4F4F-829D-5D9D5D77F763}" />
    </filter>
  </entity>
</fetch>

Cet exemple de code montre une instruction FetchXML qui récupère les détails d’une opération de conservation.

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
  <entity name="retentionoperationdetail">
    <attribute name="retentionoperationdetailid" />
    <attribute name="name" />
    <attribute name="createdon" />
    <attribute name="retentionoperationid" />
    <attribute name="retentioncount" />
    <attribute name="isrootentity" />
    <attribute name="failedcount" />
    <attribute name="entitylogicalname" />
    <order attribute="name" descending="false" />
    <filter type="and">
      <condition attribute="retentionoperationid" operator="eq"  uitype="retentionoperation" value="{35CC1317-20B7-4F4F-829D-5D9D5D77F763}"/>
    </filter>
  </entity>
</fetch>

Cet exemple de code illustre l’instruction FetchXML qui récupère les détails sur un échec survenu lors d’une opération de conservation.

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
  <entity name="retentionfailuredetail">
    <attribute name="retentionfailuredetailid" />
    <attribute name="name" />
    <attribute name="createdon" />
    <attribute name="recordid" />
    <attribute name="operation" />
    <attribute name="message" />
    <order attribute="name" descending="false" />
    <filter type="and">
      <condition attribute="operationid" operator="eq" value="35CC1317-20B7-4F4F-829D-5D9D5D77F763" />
    </filter>
  </entity>
</fetch>

Voir aussi

Gérer les stratégies de conservation des données
Afficher les données conservées à long terme
Supprimer en bloc des données
Utiliser l’API Web Microsoft Dataverse

Notes

Pouvez-vous nous indiquer vos préférences de langue pour la documentation ? Répondez à un court questionnaire. (veuillez noter que ce questionnaire est en anglais)

Le questionnaire vous prendra environ sept minutes. Aucune donnée personnelle n’est collectée (déclaration de confidentialité).