2011-12-16 12 views
16

Ejecución del despliegue de Dynamics CRM 2011 3. Necesita actualizar periódicamente millones de registros de clientes (actualizaciones delta). Usar la actualización estándar (uno por uno) toma algunas semanas. Además, no queremos tocar el DB directamente ya que puede romper cosas en el futuro.Dynamics CRM 2011 Bulk Update

¿Existe un método de actualización masiva en la API de servicio web/REST de Dynamics CRM 2011 que podemos usar? (WhatWhereHow)

+0

claro ejemplo de granel crear o actualizar sobre la EM CRM dado en el siguiente enlace http://mscrmtutorials.blogspot.in/2014/07/bulk-insert-and-bulk-update-in-ms-crm.html –

+0

¿Qué terminaste haciendo? usamos kingswaysoft –

Respuesta

11

Sí y no, en su mayoría no. Alguien me puede corregir si me equivoco, en cuyo caso con mucho gusto editaré/eliminaré mi respuesta, pero todo lo que se hace en Dynamics CRM se realiza de a uno por vez. Ni siquiera trata de manejar inserciones/actualizaciones/eliminaciones basadas en conjuntos. Entonces, a menos que vayas directamente a operaciones DB directas, te llevará semanas.

webservice does allow for "bulk" inserts/deletes/updates, pero puse "en masa" entre comillas porque todo lo que hace es configurar un proceso asincrónico donde realiza todas las operaciones de datos relevantes, sí, una a la vez. Hay una sección del SDK que aborda este tipo de gestión de datos (vinculada). Y para actualizar los registros de esta manera, primero tendría que sufrir la sobrecarga de seleccionar todos los datos que desea actualizar, luego crear un archivo xml que contenga los datos y finalmente actualizar los datos (recuerde: una fila a la vez)) Por lo tanto, sería más eficiente simplemente recorrer sus datos y emitir una solicitud Update para cada uno.

(Voy a señalar que nuestro org no ha experimentado ningún problema memorables en materia de acceso DB directa para manejar lo que el SDK no, ni he visto nada en mis lecturas de Internet personales que sugieren que otros tienen.)

Editar:

Sede de iFirefly answer abajo para algunas otras excelentes formas de abordar este problema.

1

No estoy seguro de cómo va esto con millones de registros, pero puede seleccionar sus registros, luego haga clic en el botón Editar en la cinta. Aparecerá el cuadro de diálogo "Editar múltiples registros". Cualquier cambio que haga se aplicará a todos sus registros.

+0

Todas las actualizaciones son individuales y ocurren regularmente. Actualizaciones de Delta de registros de clientes = cambios de direcciones de personas, números de teléfono, etc. –

15

Me doy cuenta de que esta publicación tiene más de 2 años, pero puedo agregarla en caso de que alguien más la lea y tenga una necesidad similar.

La respuesta de Peter Majeed está en el objetivo porque los procesos de CRM solicitan un registro a la vez. No hay una edición masiva que funcione de la manera que estás buscando. Te animo a que no toques el DB directamente si necesitas/necesitas soporte de Microsoft.

Si está buscando actualizaciones periódicas de millones de registros, tiene algunas opciones. Considere usar Scribe o desarrolle su propia herramienta de importación personalizada o script usando CRM SDK.

Escriba probablemente sea su mejor opción, ya que es rentable para la importación de datos y le permitirá actualizar e insertar fácilmente desde el mismo archivo.

Si escribe su propia utilidad basada en .Net/SDK, sugiero que sea multiproceso y rompa programáticamente su archivo de entrada en la memoria o en el disco y haga que cada subproceso funcione con su propio subconjunto de datos; es, por supuesto, si el orden de ejecución no tiene que ser cronológico según el contenido del archivo de entrada. Si puede dividir y conquistar el archivo de entrada a través de múltiples hilos, puede reducir considerablemente el tiempo de ejecución general. Además, si su política corporativa le permite tener acceso a uno de los Servidores CRM y puede colocar su código directamente en el servidor y ejecutarlo desde allí, puede eliminar la latencia de red entre una estación de trabajo que ejecuta el código y la web CRM servicios.

Por último, si este gran volumen de datos de importación proviene de otro sistema, puede escribir un complemento de CRM para ejecutar en los mensajes Retrieve y RetrieveMultiple (eventos) en CRM para su entidad específica, recuperar mediante programación los datos deseados del otro sistema (y si el otro sistema no está disponible, simplemente use la copia almacenada en caché en CRM), y mantenga CRM actualizado en tiempo real o en la base de "último almacenamiento en caché". Sin duda, este es un esfuerzo de codificación mayor, pero elimina potencialmente la necesidad de ejecutar un gran trabajo de sincronización cada pocas semanas.

6

Me doy cuenta de que esta es una vieja pregunta, pero aparece en "CRM Bulk Update" por lo que el Update Rollup 12 feature ExecuteMultiple debe mencionarse aquí - no va a solucionar su problema (volumen masivo) porque como iFirefly y Peter apuntan nuestro CRM hace todo de a uno por vez. Lo que hace es empaquetar todas sus solicitudes en un solo sobre, permitiendo que CRM maneje la ejecución de cada actualización y reduzca el número de viajes de ida y vuelta entre su aplicación y el servidor si termina emitiendo una solicitud Update para cada registro.

0

Trabajé en un proyecto de migración de datos muy grande para Dynamics CRM 2011. Necesitábamos cargar aproximadamente 3 millones de registros durante un fin de semana. Terminé construyendo una aplicación de consola (hilo único) y ejecuté varias instancias en varias máquinas. Cada aplicación de consola tenía una identificación (1, 2, etc.) y era responsable de cargar los segmentos de los datos en base a una cláusula SQL WHERE única que coincidía con la id de la aplicación.

Puede hacer lo mismo con las actualizaciones. Cada instancia puede consultar un subconjunto de los registros para actualizar y puede realizar las actualizaciones a través del SDK. Dado que cargamos millones de registros durante un fin de semana, creo que podría realizar millones de actualizaciones (si son relativamente pequeñas) en unas pocas horas.

0

equipo de Microsoft Dynamics CRM para PFE escribió nueva Another CRM SDK library que hacen uso de paralelización a mayor ejecutar peticiones para garantizar la seguridad hilo.

Puede intentar: cumplimiento a las solicitudes paralelas Me interesaría saber si funciona y las escalas a millones de registros.

1

La API BulkUpdate funciona bien para mí; es 10 veces más rápido que actualizar los registros uno a la vez. A continuación se muestra un fragmento que realiza una actualización masiva:

public override ExecuteMultipleResponse BulkUpdate(List<Entity> entities) 
    { 
     ExecuteMultipleRequest request = new ExecuteMultipleRequest() 
     { 
      Settings = new ExecuteMultipleSettings() 
      { 
       ContinueOnError = true, 
       ReturnResponses = true 
      }, 
      Requests = new OrganizationRequestCollection() 
     }; 

     for (int i = 0; i < entities.Count; i++) 
     { 
      request.Requests.Add(new UpdateRequest() { Target = entities[i] }); 
     } 

     return (ExecuteMultipleResponse) ServiceContext.Execute(request); 
    } 
0

CRM no implementa una forma de actualizar los datos masivos; Hay 3 formas de mejorar el rendimiento de la operación de actualización masiva, pero internamente no pueden cambiar el hecho de que las actualizaciones de CRM se registran una por una. Básicamente las ideas son:

  • reducir el tiempo perdido en la comunicación con el servidor CRM
  • uso paralelismo hacer múltiples operaciones al mismo tiempo
  • asegúrese de que el proceso de actualización no activa ningún flujo de trabajo/plugins. De lo contrario, puede que nunca ver el final del proceso ...

3 maneras de mejorar el rendimiento mayor operación:

  1. Después RollUp 12 hay una característica ExecuteMultipleRequest, lo que le permite enviar hasta 1000 solicitudes a la vez. Esto significa que puede ahorrar algo de tiempo en el envío de 1000 solicitudes al servicio web de CRM, sin embargo, estas solicitudes se procesan una detrás de otra.Entonces, si su servidor CRM está bien configurado, lo más probable es que este método no ayude demasiado.
  2. Puede usar la instancia OrganizationServiceContext para realizar una actualización masiva. OrganizationServiceContext implementa el patrón de unidad de trabajo para que pueda hacer múltiples actualizaciones y transmitir estas operaciones al servidor en una sola llamada. Si se compara con ExecuteMultipleRequest, no tiene un límite en el importe de la solicitud, pero si se produce un error durante la actualización, se revertirán todos los cambios.
  3. Usa multihilo o multitarea. De cualquier forma, mejoraría la velocidad, pero es probable que generen algunas fallas de conexión o errores de SQL, por lo que necesitaría agregar alguna lógica de reintento en el código.
1

Esta es una pregunta bastante antigua, pero nadie mencionó la manera rápida (pero también la más desafiante) de actualizar/crear grandes cantidades de registros en CRM 201X, utilizando la función de importación incorporada, que es totalmente factible CRM SDK. Hay un artículo perfecto de MSDN al respecto: https://msdn.microsoft.com/en-us/library/gg328321(v=crm.5).aspx. En resumen se tiene que:

1) Construir archivo de Excel que contiene los datos que desea importar (exportar simplemente algunos datos de CRM 201X y comprobar cómo la estructura se parece, recuerde que las 3 primeras columnas se ocultan)

2) crear mapa de importación entidad (especificar el archivo que ha creado)

3) crear asignaciones de columnas si es necesario

4) crear importación y iMPORTFILE entidad, proporcionando asignaciones adecuadas

5) Analizar datos utilizando ParseImportRequest

6) de datos utilizando TRANFORM TransformImportRequest

7) Importar datos utilizando ImportRecordsImportRequest

Este fueron los pasos para CRM 2011, ahora en 2017 tenemos más versiones disponibles y hay ligeras diferencias entre ellos. Compruebe el ejemplo que está disponible en MSDN y en el SDK: https://msdn.microsoft.com/en-us/library/hh547396(v=crm.5).aspx

del punto 1, por supuesto, va a ser la parte más difícil, porque hay que construir XML o docx perfectamente que corresponde a lo CRM espera, pero estoy asumiendo que lo está haciendo desde una aplicación externa, por lo que puede usar algunas geniales bibliotecas .NET que harán las cosas mucho más simples.

Nunca vi nada más rápido que la importación de CRM estándar cuando se trata de actualizar/crear registros, incluso si se realizan solicitudes de paralelismo y Actualización por lotes.

Si algo va mal con los sitios de MSDN, les dejo aquí un ejemplo desde el enlace anterior que está mostrando cómo importar datos de CRM mediante programación:

using System; 
using System.ServiceModel; 
using System.Collections.Generic; 
using System.Linq; 

// These namespaces are found in the Microsoft.Xrm.Sdk.dll assembly 
// located in the SDK\bin folder of the SDK download. 
using Microsoft.Xrm.Sdk; 
using Microsoft.Xrm.Sdk.Query; 
using Microsoft.Xrm.Sdk.Client; 
using Microsoft.Xrm.Sdk.Messages; 
using Microsoft.Xrm.Sdk.Metadata; 

// These namespaces are found in the Microsoft.Crm.Sdk.Proxy.dll assembly 
// located in the SDK\bin folder of the SDK download. 
using Microsoft.Crm.Sdk.Messages; 

namespace Microsoft.Crm.Sdk.Samples 
{  
    /// <summary> 
    /// This sample shows how to define a complex mapping for importing and then use the 
    /// Microsoft Dynamics CRM 2011 API to bulk import records with that mapping. 
    /// </summary> 
    public class ImportWithCreate 
    { 
     #region Class Level Members 

     private OrganizationServiceProxy _serviceProxy; 
     private DateTime _executionDate; 

     #endregion 

     /// <summary> 
     /// This method first connects to the organization service. Afterwards, 
     /// auditing is enabled on the organization, account entity, and a couple 
     /// of attributes. 
     /// </summary> 
     /// <param name="serverConfig">Contains server connection information.</param> 
     /// <param name="promptforDelete">When True, the user will be prompted to delete all 
     /// created entities.</param> 
     public void Run(ServerConnection.Configuration serverConfig, bool promptforDelete) 
     { 
      using (_serviceProxy = ServerConnection.GetOrganizationProxy(serverConfig)) 
      { 
       // This statement is required to enable early bound type support. 
       _serviceProxy.EnableProxyTypes(); 

       // Log the start time to ensure deletion of records created during execution. 
       _executionDate = DateTime.Today; 
       ImportRecords(); 
       DeleteRequiredRecords(promptforDelete); 
      } 
     } 

     /// <summary> 
     /// Imports records to Microsoft Dynamics CRM from the specified .csv file. 
     /// </summary> 
     public void ImportRecords() 
     { 
      // Create an import map. 
      ImportMap importMap = new ImportMap() 
      { 
       Name = "Import Map " + DateTime.Now.Ticks.ToString(), 
       Source = "Import Accounts.csv", 
       Description = "Description of data being imported", 
       EntitiesPerFile = 
        new OptionSetValue((int)ImportMapEntitiesPerFile.SingleEntityPerFile), 
       EntityState = EntityState.Created 
      }; 
      Guid importMapId = _serviceProxy.Create(importMap); 

      // Create column mappings. 

      #region Column One Mappings 
      // Create a column mapping for a 'text' type field. 
      ColumnMapping colMapping1 = new ColumnMapping() 
      { 
       // Set source properties. 
       SourceAttributeName = "src_name", 
       SourceEntityName = "Account_1", 

       // Set target properties. 
       TargetAttributeName = "name", 
       TargetEntityName = Account.EntityLogicalName, 

       // Relate this column mapping with the data map. 
       ImportMapId = 
        new EntityReference(ImportMap.EntityLogicalName, importMapId), 

       // Force this column to be processed. 
       ProcessCode = 
        new OptionSetValue((int)ColumnMappingProcessCode.Process) 
      }; 

      // Create the mapping. 
      Guid colMappingId1 = _serviceProxy.Create(colMapping1); 
      #endregion 

      #region Column Two Mappings 
      // Create a column mapping for a 'lookup' type field. 
      ColumnMapping colMapping2 = new ColumnMapping() 
      { 
       // Set source properties. 
       SourceAttributeName = "src_parent", 
       SourceEntityName = "Account_1", 

       // Set target properties. 
       TargetAttributeName = "parentaccountid", 
       TargetEntityName = Account.EntityLogicalName, 

       // Relate this column mapping with the data map. 
       ImportMapId = 
        new EntityReference(ImportMap.EntityLogicalName, importMapId), 

       // Force this column to be processed. 
       ProcessCode = 
        new OptionSetValue((int)ColumnMappingProcessCode.Process), 
      }; 

      // Create the mapping. 
      Guid colMappingId2 = _serviceProxy.Create(colMapping2); 

      // Because we created a column mapping of type lookup, we need to specify lookup details in a lookupmapping. 
      // One lookupmapping will be for the parent account, and the other for the current record. 
      // This lookupmapping is important because without it the current record 
      // cannot be used as the parent of another record. 

      // Create a lookup mapping to the parent account. 
      LookUpMapping parentLookupMapping = new LookUpMapping() 
      { 
       // Relate this mapping with its parent column mapping. 
       ColumnMappingId = 
        new EntityReference(ColumnMapping.EntityLogicalName, colMappingId2), 

       // Force this column to be processed. 
       ProcessCode = 
        new OptionSetValue((int)LookUpMappingProcessCode.Process), 

       // Set the lookup for an account entity by its name attribute. 
       LookUpEntityName = Account.EntityLogicalName, 
       LookUpAttributeName = "name", 
       LookUpSourceCode = 
        new OptionSetValue((int)LookUpMappingLookUpSourceCode.System) 
      }; 

      // Create the lookup mapping. 
      Guid parentLookupMappingId = _serviceProxy.Create(parentLookupMapping); 

      // Create a lookup on the current record's "src_name" so that this record can 
      // be used as the parent account for another record being imported. 
      // Without this lookup, no record using this account as its parent will be imported. 
      LookUpMapping currentLookUpMapping = new LookUpMapping() 
      { 
       // Relate this lookup with its parent column mapping. 
       ColumnMappingId = 
        new EntityReference(ColumnMapping.EntityLogicalName, colMappingId2), 

       // Force this column to be processed. 
       ProcessCode = 
        new OptionSetValue((int)LookUpMappingProcessCode.Process), 

       // Set the lookup for the current record by its src_name attribute. 
       LookUpAttributeName = "src_name", 
       LookUpEntityName = "Account_1", 
       LookUpSourceCode = 
        new OptionSetValue((int)LookUpMappingLookUpSourceCode.Source) 
      }; 

      // Create the lookup mapping 
      Guid currentLookupMappingId = _serviceProxy.Create(currentLookUpMapping); 
      #endregion 

      #region Column Three Mappings 
      // Create a column mapping for a 'picklist' type field 
      ColumnMapping colMapping3 = new ColumnMapping() 
      { 
       // Set source properties 
       SourceAttributeName = "src_addresstype", 
       SourceEntityName = "Account_1", 

       // Set target properties 
       TargetAttributeName = "address1_addresstypecode", 
       TargetEntityName = Account.EntityLogicalName, 

       // Relate this column mapping with its parent data map 
       ImportMapId = 
        new EntityReference(ImportMap.EntityLogicalName, importMapId), 

       // Force this column to be processed 
       ProcessCode = 
        new OptionSetValue((int)ColumnMappingProcessCode.Process) 
      }; 

      // Create the mapping 
      Guid colMappingId3 = _serviceProxy.Create(colMapping3); 

      // Because we created a column mapping of type picklist, we need to specify picklist details in a picklistMapping 
      PickListMapping pickListMapping1 = new PickListMapping() 
      { 
       SourceValue = "bill", 
       TargetValue = 1, 

       // Relate this column mapping with its column mapping data map 
       ColumnMappingId = 
        new EntityReference(ColumnMapping.EntityLogicalName, colMappingId3), 

       // Force this column to be processed 
       ProcessCode = 
        new OptionSetValue((int)PickListMappingProcessCode.Process) 
      }; 

      // Create the mapping 
      Guid picklistMappingId1 = _serviceProxy.Create(pickListMapping1); 

      // Need a picklist mapping for every address type code expected 
      PickListMapping pickListMapping2 = new PickListMapping() 
      { 
       SourceValue = "ship", 
       TargetValue = 2, 

       // Relate this column mapping with its column mapping data map 
       ColumnMappingId = 
        new EntityReference(ColumnMapping.EntityLogicalName, colMappingId3), 

       // Force this column to be processed 
       ProcessCode = 
        new OptionSetValue((int)PickListMappingProcessCode.Process) 
      }; 

      // Create the mapping 
      Guid picklistMappingId2 = _serviceProxy.Create(pickListMapping2); 
      #endregion 

      // Create Import 
      Import import = new Import() 
      { 
       // IsImport is obsolete; use ModeCode to declare Create or Update. 
       ModeCode = new OptionSetValue((int)ImportModeCode.Create), 
       Name = "Importing data" 
      }; 
      Guid importId = _serviceProxy.Create(import); 

      // Create Import File. 
      ImportFile importFile = new ImportFile() 
      { 
       Content = BulkImportHelper.ReadCsvFile("Import Accounts.csv"), // Read contents from disk. 
       Name = "Account record import", 
       IsFirstRowHeader = true, 
       ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId), 
       UseSystemMap = false, 
       Source = "Import Accounts.csv", 
       SourceEntityName = "Account_1", 
       TargetEntityName = Account.EntityLogicalName, 
       ImportId = new EntityReference(Import.EntityLogicalName, importId), 
       EnableDuplicateDetection = false, 
       FieldDelimiterCode = 
        new OptionSetValue((int)ImportFileFieldDelimiterCode.Comma), 
       DataDelimiterCode = 
        new OptionSetValue((int)ImportFileDataDelimiterCode.DoubleQuote), 
       ProcessCode = 
        new OptionSetValue((int)ImportFileProcessCode.Process) 
      }; 

      // Get the current user to set as record owner. 
      WhoAmIRequest systemUserRequest = new WhoAmIRequest(); 
      WhoAmIResponse systemUserResponse = 
       (WhoAmIResponse)_serviceProxy.Execute(systemUserRequest); 

      // Set the owner ID.     
      importFile.RecordsOwnerId = 
       new EntityReference(SystemUser.EntityLogicalName, systemUserResponse.UserId); 

      Guid importFileId = _serviceProxy.Create(importFile); 

      // Retrieve the header columns used in the import file. 
      GetHeaderColumnsImportFileRequest headerColumnsRequest = new GetHeaderColumnsImportFileRequest() 
      { 
       ImportFileId = importFileId 
      }; 
      GetHeaderColumnsImportFileResponse headerColumnsResponse = 
       (GetHeaderColumnsImportFileResponse)_serviceProxy.Execute(headerColumnsRequest); 

      // Output the header columns. 
      int columnNum = 1; 
      foreach (string headerName in headerColumnsResponse.Columns) 
      { 
       Console.WriteLine("Column[" + columnNum.ToString() + "] = " + headerName); 
       columnNum++; 
      } 

      // Parse the import file. 
      ParseImportRequest parseImportRequest = new ParseImportRequest() 
      { 
       ImportId = importId 
      }; 
      ParseImportResponse parseImportResponse = 
       (ParseImportResponse)_serviceProxy.Execute(parseImportRequest); 
      Console.WriteLine("Waiting for Parse async job to complete"); 
      BulkImportHelper.WaitForAsyncJobCompletion(_serviceProxy, parseImportResponse.AsyncOperationId); 
      BulkImportHelper.ReportErrors(_serviceProxy, importFileId); 

      // Retrieve the first two distinct values for column 1 from the parse table. 
      // NOTE: You must create the parse table first using the ParseImport message. 
      // The parse table is not accessible after ImportRecordsImportResponse is called. 
      GetDistinctValuesImportFileRequest distinctValuesRequest = new GetDistinctValuesImportFileRequest() 
      { 
       columnNumber = 1, 
       ImportFileId = importFileId, 
       pageNumber = 1, 
       recordsPerPage = 2, 
      }; 
      GetDistinctValuesImportFileResponse distinctValuesResponse = 
       (GetDistinctValuesImportFileResponse)_serviceProxy.Execute(distinctValuesRequest); 

      // Output the distinct values. In this case: (column 1, row 1) and (column 1, row 2). 
      int cellNum = 1; 
      foreach (string cellValue in distinctValuesResponse.Values) 
      { 
       Console.WriteLine("(1, " + cellNum.ToString() + "): " + cellValue); 
       Console.WriteLine(cellValue); 
       cellNum++; 
      } 

      // Retrieve data from the parse table. 
      // NOTE: You must create the parse table first using the ParseImport message. 
      // The parse table is not accessible after ImportRecordsImportResponse is called. 
      RetrieveParsedDataImportFileRequest parsedDataRequest = new RetrieveParsedDataImportFileRequest() 
      { 
       ImportFileId = importFileId, 
       PagingInfo = new PagingInfo() 
       { 
        // Specify the number of entity instances returned per page. 
        Count = 2, 
        // Specify the number of pages returned from the query. 
        PageNumber = 1, 
        // Specify a total number of entity instances returned. 
        PagingCookie = "1" 
       } 
      }; 

      RetrieveParsedDataImportFileResponse parsedDataResponse = 
       (RetrieveParsedDataImportFileResponse)_serviceProxy.Execute(parsedDataRequest); 

      // Output the first two rows retrieved. 
      int rowCount = 1; 
      foreach (string[] rows in parsedDataResponse.Values) 
      { 
       int colCount = 1; 
       foreach (string column in rows) 
       { 
        Console.WriteLine("(" + rowCount.ToString() + "," + colCount.ToString() + ") = " + column); 
        colCount++; 
       } 
       rowCount++; 
      } 

      // Transform the import 
      TransformImportRequest transformImportRequest = new TransformImportRequest() 
      { 
       ImportId = importId 
      }; 
      TransformImportResponse transformImportResponse = 
       (TransformImportResponse)_serviceProxy.Execute(transformImportRequest); 
      Console.WriteLine("Waiting for Transform async job to complete"); 
      BulkImportHelper.WaitForAsyncJobCompletion(_serviceProxy, transformImportResponse.AsyncOperationId); 
      BulkImportHelper.ReportErrors(_serviceProxy, importFileId); 

      // Upload the records. 
      ImportRecordsImportRequest importRequest = new ImportRecordsImportRequest() 
      { 
       ImportId = importId 
      }; 
      ImportRecordsImportResponse importResponse = 
       (ImportRecordsImportResponse)_serviceProxy.Execute(importRequest); 
      Console.WriteLine("Waiting for ImportRecords async job to complete"); 
      BulkImportHelper.WaitForAsyncJobCompletion(_serviceProxy, importResponse.AsyncOperationId); 
      BulkImportHelper.ReportErrors(_serviceProxy, importFileId); 
     } 

     /// <summary> 
     /// Deletes any entity records that were created for this sample. 
     /// <param name="prompt">Indicates whether to prompt the user 
     /// to delete the records created in this sample.</param> 
     /// </summary> 
     public void DeleteRequiredRecords(bool prompt) 
     { 
      bool toBeDeleted = true; 

      if (prompt) 
      { 
       // Ask the user if the created entities should be deleted. 
       Console.Write("\nDo you want these entity records deleted? (y/n) [y]: "); 
       String answer = Console.ReadLine(); 
       if (answer.StartsWith("y") || 
        answer.StartsWith("Y") || 
        answer == String.Empty) 
       { 
        toBeDeleted = true; 
       } 
       else 
       { 
        toBeDeleted = false; 
       } 
      } 

      if (toBeDeleted) 
      { 
       // Retrieve all account records created in this sample. 
       QueryExpression query = new QueryExpression() 
       { 
        EntityName = Account.EntityLogicalName, 
        Criteria = new FilterExpression() 
        { 
         Conditions = 
         { 
          new ConditionExpression("createdon", ConditionOperator.OnOrAfter, _executionDate), 
         } 
        }, 
        ColumnSet = new ColumnSet(false) 
       }; 
       var accountsCreated = _serviceProxy.RetrieveMultiple(query).Entities; 

       // Delete all records created in this sample. 
       foreach (var account in accountsCreated) 
       { 
        _serviceProxy.Delete(Account.EntityLogicalName, account.Id); 
       } 

       Console.WriteLine("Entity record(s) have been deleted."); 
      } 
     } 
     #region Main method 

     /// <summary> 
     /// Standard Main() method used by most SDK samples. 
     /// </summary> 
     /// <param name="args"></param> 
     static public void Main(string[] args) 
     { 
      try 
      { 
       // Obtain the target organization's web address and client logon 
       // credentials from the user. 
       ServerConnection serverConnect = new ServerConnection(); 
       ServerConnection.Configuration config = serverConnect.GetServerConfiguration(); 

       var app = new ImportWithCreate(); 
       app.Run(config, true); 
      } 

      catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> ex) 
      { 
       Console.WriteLine("The application terminated with an error."); 
       Console.WriteLine("Timestamp: {0}", ex.Detail.Timestamp); 
       Console.WriteLine("Code: {0}", ex.Detail.ErrorCode); 
       Console.WriteLine("Message: {0}", ex.Detail.Message); 
       Console.WriteLine("Trace: {0}", ex.Detail.TraceText); 
       Console.WriteLine("Inner Fault: {0}", 
        null == ex.Detail.InnerFault ? "No Inner Fault" : "Has Inner Fault"); 
      } 
      catch (System.TimeoutException ex) 
      { 
       Console.WriteLine("The application terminated with an error."); 
       Console.WriteLine("Message: {0}", ex.Message); 
       Console.WriteLine("Stack Trace: {0}", ex.StackTrace); 
       Console.WriteLine("Inner Fault: {0}", 
        null == ex.InnerException.Message ? "No Inner Fault" : ex.InnerException.Message); 
      } 
      catch (System.Exception ex) 
      { 
       Console.WriteLine("The application terminated with an error."); 
       Console.WriteLine(ex.Message); 

       // Display the details of the inner exception. 
       if (ex.InnerException != null) 
       { 
        Console.WriteLine(ex.InnerException.Message); 

        FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault> fe = ex.InnerException 
         as FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>; 
        if (fe != null) 
        { 
         Console.WriteLine("Timestamp: {0}", fe.Detail.Timestamp); 
         Console.WriteLine("Code: {0}", fe.Detail.ErrorCode); 
         Console.WriteLine("Message: {0}", fe.Detail.Message); 
         Console.WriteLine("Trace: {0}", fe.Detail.TraceText); 
         Console.WriteLine("Inner Fault: {0}", 
          null == fe.Detail.InnerFault ? "No Inner Fault" : "Has Inner Fault"); 
        } 
       } 
      } 
      // Additional exceptions to catch: SecurityTokenValidationException, ExpiredSecurityTokenException, 
      // SecurityAccessDeniedException, MessageSecurityException, and SecurityNegotiationException. 

      finally 
      { 
       Console.WriteLine("Press <Enter> to exit."); 
       Console.ReadLine(); 
      } 
     } 
     #endregion Main method 
    } 
} 
Cuestiones relacionadas