Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All

Start an Asynchronous Bulk Delete Job and Review Results

banner art

[Applies to: Microsoft Dynamics CRM 4.0]

Find the latest SDK documentation: CRM 2015 SDK

The following code example shows how to perform a bulk delete asynchronous operation. Then it shows how to view the error details for every bulk delete failure object associated with a successful bulk delete operation.

This sample code can be found in the following files in the SDK download:


For more information about the helper methods in the Microsoft.Crm.Sdk.Utility.CrmServiceUtility namespace, see Utility Sample Code.


using System;
using System.Xml;
using CrmSdk;
using Microsoft.Crm.Sdk.Utility;

namespace Microsoft.Crm.Sdk.HowTo.BulkDelete
   public class BulkDeleteOperations
      public BulkDeleteOperations()

      public static bool Run(string crmServerUrl, string orgName)
         bool success = true;
            // Set up the CRM Service.  
            CrmService service = Microsoft.Crm.Sdk.Utility.CrmServiceUtility.GetCrmService(crmServerUrl, orgName);
            service.PreAuthenticate = true;
            // Query for a system user to send an e-mail message to after the bulk delete operation completes.
            WhoAmIRequest userRequest = new WhoAmIRequest();
            WhoAmIResponse userResponse = (WhoAmIResponse)service.Execute(userRequest);
            Guid currentUserId = userResponse.UserId;
            // Create a condition for a bulk delete request.
            // Note: If no records are found that match this condition, the bulk delete will not fail.
            // It will succeed with 0 successes and 0 failures.
            ConditionExpression deleteCondition = new ConditionExpression();
            deleteCondition.AttributeName = "name";
            deleteCondition.Operator = ConditionOperator.Equal;
            deleteCondition.Values = new string[] { "Fourth Coffee" };

            // Create a fiter expression for a buld delete request.
            FilterExpression deleteFilter = new FilterExpression();
            deleteFilter.Conditions = new ConditionExpression[] { deleteCondition };

            // Create the bulk delete query set.
            QueryExpression bulkDeleteQuery = new QueryExpression();
            bulkDeleteQuery.EntityName = EntityName.account.ToString();
            // Return all records.
            bulkDeleteQuery.Distinct = false;
            bulkDeleteQuery.Criteria = deleteFilter;
            // Create the bulk delete request.
            BulkDeleteRequest bulkDeleteRequest = new BulkDeleteRequest();
            // Set the request properties.
            bulkDeleteRequest.JobName = "Sample Bulk Delete";
            bulkDeleteRequest.QuerySet = new QueryBase[] { bulkDeleteQuery };
            // Set the start time for the bulk delete.
            bulkDeleteRequest.StartDateTime = new CrmDateTime();
            bulkDeleteRequest.StartDateTime.Value = DateTime.Now.ToString();
            // Provide a recurrence pattern  so that the job runs one time every day.
            // SDK: bulkDeleteRequest.RecurrencePattern = String.Format(System.Globalization.CultureInfo.InvariantCulture, "FREQ=DAILY;INTERVAL={0};", 1);
            bulkDeleteRequest.RecurrencePattern = String.Empty;

            // Set e-mail activity properties.
            // SDK: bulkDeleteRequest.SendEmailNotification = true;
            bulkDeleteRequest.SendEmailNotification = false;
            bulkDeleteRequest.ToRecipients = new Guid[] { currentUserId };
            bulkDeleteRequest.CCRecipients = new Guid[] { };

            // Submit the bulk delete job.
            // Note: Because this is an asynchronous operation, the response will be immediate.
            BulkDeleteResponse bulkDeleteResponse = (BulkDeleteResponse)service.Execute(bulkDeleteRequest);

            // To monitor the asynchronous operation, retrieve the bulkdeleteoperation object.
            // Note: There will be a period of time from when the asynchronous operation request was submitted to the time
            // when a successful query for that operation can be made.  When you use Plug-ins, events can be 
            // subscribed to that will occur when the asynchronous operation status changes.
            QueryByAttribute bulkQuery = new QueryByAttribute();
            // Be aware that using AllColumns may adversely affect
            // performance and cause unwanted cascading in subsequent 
            // updates. A best practice is to retrieve the least amount of 
            // data required.
            bulkQuery.ColumnSet = new AllColumns();
            bulkQuery.EntityName = EntityName.bulkdeleteoperation.ToString();

            // Note: When the bulk delete operation was submitted, the GUID that was returned 
            // was the asyncoperationid, not the bulkdeleteoperationid.
            bulkQuery.Attributes = new string[] { "asyncoperationid" };
            bulkQuery.Values = new object[1];
            bulkQuery.Values[0] = bulkDeleteResponse.JobId;

            // With only the asyncoperationid at this point, a RetrieveMultiple is required to get the
            // bulk delete operation that was created.
            BusinessEntityCollection entityCollection = service.RetrieveMultiple(bulkQuery);
            bulkdeleteoperation createdBulkDeleteOperation = null;

            // Monitor the asynchronous operation by using polling until it is complete or the max polling time expires.
            const int ARBITRARY_MAX_POLLING_TIME = 60;
            int secondsTicker = ARBITRARY_MAX_POLLING_TIME;
            while (secondsTicker > 0)
               // Make sure that the asynchronous operation was retrieved.
               if (entityCollection.BusinessEntities.Length > 0)
                  // Grab the one bulk operation that was created.
                  createdBulkDeleteOperation = (bulkdeleteoperation)entityCollection.BusinessEntities[0];
                  // Check the operation's state.
                  if (createdBulkDeleteOperation.statecode.Value != BulkDeleteOperationState.Completed)
                     // The operation has not yet completed. Wait one second for the status to change.
                     // Retrieve a fresh version of the bulk delete operation.
                     entityCollection = service.RetrieveMultiple(bulkQuery);
                     // Stop polling because the operation's state is now finished.
                     secondsTicker = 0;
                  // Wait one second for the asynchronous operation to become active.

                  // Retrieve the entity again.
                  entityCollection = service.RetrieveMultiple(bulkQuery);

            // Export the fetch xml (query) used for bulk delete.
            XmlDocument xmlDoc = new XmlDocument();
            // Check for the number of successful deletes.
            int successfulDeletes = createdBulkDeleteOperation.successcount.Value;
            // Check for any failures that might have occured during the bulk delete operation.
            if (createdBulkDeleteOperation.failurecount.Value > 0)
               // Query for all the failures.
               QueryByAttribute failureQuery = new QueryByAttribute();
            // Be aware that using AllColumns may adversely affect
            // performance and cause unwanted cascading in subsequent 
            // updates. A best practice is to retrieve the least amount of 
            // data required.
               failureQuery.ColumnSet = new AllColumns();
               failureQuery.EntityName = EntityName.bulkdeletefailure.ToString();
               failureQuery.Attributes = new string[] { "bulkdeleteoperationid" };
               failureQuery.Values = new object[1];
               failureQuery.Values[0] = createdBulkDeleteOperation.bulkdeleteoperationid.Value;

               // Retrieve the bulkdeletefailure objects.
               entityCollection = service.RetrieveMultiple(failureQuery);

               // Examine each failure for information about the failure.
               foreach (bulkdeletefailure failureOperation in entityCollection.BusinessEntities)
                  // Process failure information.

            #region check success
            // Validate that the operation was completed.
            if (createdBulkDeleteOperation.statecode.Value != BulkDeleteOperationState.Completed)
               // This happens if it took longer than the polling time allowed 
               // for this operation to finish.
               success = false;
               if (createdBulkDeleteOperation.statuscode.name != "Succeeded")
                  success = false;


            #region Remove Data Required for this Sample

            // Note: The bulkdeleteoperation entity cannot be removed from the database.

         catch (System.Web.Services.Protocols.SoapException)
            // Perform error handling here.
         catch (Exception)

         return success;

See Also



© 2010 Microsoft Corporation. All rights reserved.

© 2015 Microsoft