Compartir por


Retención de datos a largo plazo

Retención de datos a largo plazo automatiza la transferencia de datos desde su base de datos transaccional de Microsoft Dataverse a un lago de datos administrado para un almacenamiento rentable de archivos. Comience por configurar tablas para la retención a largo plazo. Luego, cree directivas de retención que definan los datos a archivar. Las ejecuciones de retención programadas transfieren filas que coinciden con los criterios.

Importante

Para utilizar todas las funciones de retención de datos a largo plazo, debe cumplir con los dos requisitos que se describen aquí: Descripción general de la retención de datos a largo plazo de Dataverse.

Recuperar datos retenidos

Puede recuperar datos que se han conservado utilizando FetchXml y QueryExpression .

Con FetchXml, establezca el valor del atributo elemento de búsqueda datasource en "retained".

<fetch datasource="retained">
   <entity name="account">
      <attribute name="accountId" />
   </entity>
</fetch>

Con QueryExpression, establezca la propiedad QueryExpression.DataSource en retained.

Nota

Actualmente no hay forma de recuperar datos retenidos mediante la Dataverse API web.

Configurar una directiva de retención

Para crear directivas de retención, utilice nuestras API, el Maker Portal o la instalación de la solución. El siguiente código de ejemplo demuestra cómo usar API para crear una directiva de retención.

El siguiente código utiliza el Servicio de organización y el método IOrganizationService.Create(Entity) para crear una directiva de retención que conserva todas las oportunidades cerradas y se ejecuta anualmente. Los parámetros de recurrencia válidos son DAILY, WEEKLY, MONTHLY y YEARLY. Para ejecutar la retención solo una vez, establezca el valor de recurrencia en vacío.

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> " +
        "<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);
    }
}

El resultado de este código es "Política de retención creada con Id: c1a9e932-89f6-4f17-859c-bd2101683263".

Valide su directiva de retención

El proceso de retención a largo plazo mueve datos desde Dataverse almacenamiento transaccional a un lago de datos administrado. Ya no puede ejecutar operaciones transaccionales en los datos después de que se trasladen al lago de datos. Es importante asegurarse de que sus directivas de retención sean correctas. Puede agregar sus propias validaciones registrando opcionalmente un complemento personalizado en el mensaje 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.");
        }
    }
}

Lógica personalizada mientras se ejecuta la retención

La retención a largo plazo es un proceso asíncrono que se ejecuta cada vez que se configura una política de retención. Realiza las siguientes operaciones:

  1. Marcar filas (registros) listas para retención.
  2. Copie las filas marcadas en el lago de datos.
  3. Purgar filas de la base de datos de origen.
  4. Retroceda las filas marcadas si falla la purga.

Opcionalmente, puede registrar complementos personalizados para ejecutarlos cuando se marcan filas para retención, cuando se eliminan filas en el origen o cuando se revierten filas marcadas para retención. La escritura de código de complemento se aplica al SDK solo para programación .NET. La API web no admite el desarrollo de complementos.

Lógica personalizada cuando la fila está marcada para retención

Como parte del marcado de filas para retención, Dataverse invoca los mensajes BulkRetain y Retain. Puede agregar lógica personalizada registrando un complemento en la ejecución de esos mensajes. Algunos ejemplos de lógica personalizada incluyen marcar más filas para su retención o realizar una validación antes de marcar las filas para su retención

Este ejemplo de código muestra un complemento personalizado que se ejecuta durante la retención de una sola fila de la tabla.

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.");
        }
    }
}

Para una operación de retención de reversión, escriba su complemento de forma similar al ejemplo anterior, pero regístrelo en el mensaje RollbackRetain.

Lógica personalizada en retención masiva

Este ejemplo de código demuestra una lógica personalizada en la ejecución de la última página de una operación de mensaje 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. 
            }
        }
    }
}

Lógica personalizada cuando se elimina una fila debido a la retención

Dataverse ejecuta el mensaje PurgeRetainedContent para eliminar las filas de datos transaccionales que se movieron correctamente al lago de datos. El mensaje PurgeRetainedContent ejecuta internamente una operación de mensaje Delete para eliminar las filas de la tabla que se movieron correctamente

Puede registrar un complemento personalizado en el mensaje PurgeRetainedContent si necesita una lógica personalizada durante la operación de purga a nivel de tabla. Opcionalmente, puede registrar un complemento personalizado en el mensaje Delete si necesita invocar código cuando se elimina una fila debido a la retención. Puede determinar si la eliminación se produjo debido a la retención o no comprobando la propiedad ParentContext del complemento. El valor de propiedad ParentContext para la operación de mensaje Delete debido a la retención es "PurgeRetainedContent".

Este ejemplo de código bloquea la purga en una tabla cuando las filas no están listas para la purga

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

Este ejemplo de código se aplica a la operación de eliminación debido a la retención

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

Política de retención de consultas y detalles de ejecución

Los detalles de la política de retención se almacenan en la tabla RetentionConfig. Los detalles de ejecución de retención se almacenan en las tablas RetentionOperation y RetentionOperationDetail. Puede consultar estas tablas para obtener la política de retención y los detalles de ejecución.

El siguiente código proporciona algunos ejemplos de FetchXML que se pueden utilizar para consultar las filas de la tabla de detalles de retención de fecha. FetchXML es un lenguaje de consulta propietario basado en XML. Se puede utilizar con consultas basadas en SDK usando FetchExpression y mediante la API web usando la cadena de consulta fetchXml

Este ejemplo de código muestra una consulta simple para devolver todas las directivas de retención activas para un pedido de correo electrónico por nombre.


public EntityCollection GetActivePolicies(IOrganizationService orgService)
{
    string fetchXml = @"
    <fetch>
      <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);
}

Más ejemplos de cadenas de consulta FetchXML

Este ejemplo de código ilustra el uso de una instrucción FetchXML para recuperar todas las directivas de retención pausadas para un correo electrónico.

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

Este ejemplo de código muestra cómo utilizar una instrucción FetchXML para recuperar todas las operaciones de retención para una directiva de retención.

<fetch>
  <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" 
         value="{35CC1317-20B7-4F4F-829D-5D9D5D77F763}" />
    </filter>
  </entity>
</fetch>

Este ejemplo de código muestra una instrucción FetchXML que recupera detalles de una operación de retención.

<fetch>
  <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" value="{35CC1317-20B7-4F4F-829D-5D9D5D77F763}"/>
    </filter>
  </entity>
</fetch>

Este ejemplo de código ilustra la instrucción FetchXML que recupera detalles sobre un error que ocurrió durante una operación de retención.

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

Consulte también

Administrar directivas de retención de datos
Ver datos retenidos a largo plazo
Eliminar datos en masa
Usar la API web de Microsoft Dataverse

Nota

¿Puede indicarnos sus preferencias de idioma de documentación? Realice una breve encuesta. (tenga en cuenta que esta encuesta está en inglés)

La encuesta durará unos siete minutos. No se recopilan datos personales (declaración de privacidad).