This documentation is archived and is not being maintained.

Start a Background Bulk Delete Operation

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. It also shows how to view error details for every bulk delete failure 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
   /// <summary>
   /// This sample shows how to perform a bulk delete asynchronous 
   /// operation. It also shows how to view error details for every 
   /// bulk delete failure object associated with a successful bulk 
   /// delete operation.
   /// </summary>
   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 to after the bulk delete operation is completed.
            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 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 once every day.
            bulkDeleteRequest.RecurrencePattern = 
                    String.Format(System.Globalization.CultureInfo.InvariantCulture, "FREQ=DAILY;INTERVAL={0};", 1);

            // Set e-mail activity properties.
            bulkDeleteRequest.SendEmailNotification = true;
            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, we must retrieve the bulkdeleteoperation object
            // NOTE: There will be a period of time from when the async operation request was sumbitted to the time
            // when a successful query for that async operation can be made. When you use Plug-ins, events can be 
            // subscribed to that will occur when the async 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 async operation through polling until it is complete or max polling time expires
            const int ARBITRARY_MAX_POLLING_TIME = 60;
            int secondsTicker = ARBITRARY_MAX_POLLING_TIME;
            while (secondsTicker > 0)
               // Make sure that the async 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 a second for the status to change.
                     // Retrieve a fresh version the bulk delete operation
                     entityCollection = service.RetrieveMultiple(bulkQuery);
                     // Stop polling as the operation's state is now finished.
                     secondsTicker = 0;
                  // Wait a second for the async operation to become active.

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

            // Export 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 may 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 ( != "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.