Start a Background Bulk Delete Operation
![]() |
[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:
Server\HowTo\CS\BulkDelete\BulkDeleteOperations.cs
For more information about the helper methods in the Microsoft.Crm.Sdk.Utility.CrmServiceUtility namespace, see Utility Sample Code.
Example
[C#]
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;
try
{
// 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.
System.Threading.Thread.Sleep(1000);
secondsTicker--;
// Retrieve a fresh version the bulk delete operation
entityCollection = service.RetrieveMultiple(bulkQuery);
}
else
{
// Stop polling as the operation's state is now finished.
secondsTicker = 0;
}
}
else
{
// Wait a second for the async operation to become active.
System.Threading.Thread.Sleep(1000);
secondsTicker--;
// Retrieve the entity again.
entityCollection = service.RetrieveMultiple(bulkQuery);
}
}
// Export fetch xml (query) used for bulk delete.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(createdBulkDeleteOperation.orderedquerysetxml);
// 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
Console.WriteLine(failureOperation.regardingobjectid.name);
Console.WriteLine(failureOperation.regardingobjectid.type);
Console.WriteLine(failureOperation.regardingobjectid.Value.ToString());
}
}
#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;
}
else
{
if (createdBulkDeleteOperation.statuscode.name != "Succeeded")
{
success = false;
}
}
#endregion
#region Remove Data Required for this Sample
// NOTE: The bulkdeleteoperation entity cannot be removed from the database
#endregion
}
catch (System.Web.Services.Protocols.SoapException)
{
// Perform error handling here.
throw;
}
catch (Exception)
{
throw;
}
return success;
}
}
}
See Also
Concepts
- Bulk Delete
- Bulk Delete Operation Entity Capabilities
- Bulk Delete Failure Entity Capabilities
- Recurrence Pattern in Asynchronous Job Execution
Reference
.gif)