【问题标题】:How to delete records between two dates in bulk?如何批量删除两个日期之间的记录?
【发布时间】:2018-08-02 13:54:44
【问题描述】:

我想删除两个日期之间的记录。我使用 Fetchxml 表达式来获取两个日期之间每条记录的 GUID,然后我使用 service.Delete。这是我的代码:

string fetchXml = @" <fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
                        <entity name='new_units'>
                            <link-entity name='new_alterunitorder' from ='new_orderlineid' to = 'new_unitsid' >
                                <attribute name='new_alterunitorderid' />
                                <filter type='and'>
                                    <condition attribute='new_orderdate' operator='on-or-after' value='" + startDate.ToShortDateString() + @"' />
                                    <condition attribute='new_orderdate' operator='on-or-before' value='" + endDate.ToShortDateString() + @"' />
                                    <condition attribute='new_orderlineid' operator='eq' uiname='" + uiName + @"' uitype='new_units' value='" + unitOrderId + @"' />
                                </filter>
                            </link-entity>
                        </entity>
                    </fetch>";

                    EntityCollection result = service.RetrieveMultiple(new FetchExpression(fetchXml));

                    //Delete the collection 
                    foreach (var id in result.Entities)
                    {
                        var entRef = id.GetAttributeValue<EntityReference>("new_alterunitorderid");
                        var guid = (Guid)entRef.Id;
                        service.Delete("new_alterunits", guid);
                    }

FetchXML 有 5000 条记录的限制,我该如何绕过?!我还读到使用service.Delete 循环不是推荐的批量删除方式。请帮助我找到实现我想做的最好的方法!

【问题讨论】:

    标签: c# dynamics-crm microsoft-dynamics dynamics-365 dynamics-crm-365


    【解决方案1】:

    您可能还想研究通过 BulkDeleteRequest 类使用本机批量删除服务。

    下面是一个基本的例子,this article 有一个更详细的例子。如果要将 FetchXML 转换为 QueryExpression,可以使用 FetchXmlToQueryExpressionRequest 类。

    // Set the request properties.
    bulkDeleteRequest.JobName = "Backup Bulk Delete";
    
    // Querying activities
    bulkDeleteRequest.QuerySet = new QueryExpression[]
    {
        opportunitiesQuery,
        BuildActivityQuery(Task.EntityLogicalName),
        BuildActivityQuery(Fax.EntityLogicalName),
        BuildActivityQuery(PhoneCall.EntityLogicalName),
        BuildActivityQuery(Email.EntityLogicalName),
        BuildActivityQuery(Letter.EntityLogicalName),
        BuildActivityQuery(Appointment.EntityLogicalName),
        BuildActivityQuery(ServiceAppointment.EntityLogicalName),
        BuildActivityQuery(CampaignResponse.EntityLogicalName),
        BuildActivityQuery(RecurringAppointmentMaster.EntityLogicalName)
    };
    
    // Set the start time for the bulk delete.
    bulkDeleteRequest.StartDateTime = DateTime.Now;
    
    // Set the required recurrence pattern.
    bulkDeleteRequest.RecurrencePattern = String.Empty;
    
    // Set email activity properties.
    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)_serviceProxy.Execute(bulkDeleteRequest);
    Console.WriteLine("The bulk delete operation has been requested.");
    

    【讨论】:

      【解决方案2】:

      现在我们已经阐明了要求,下面是我将如何解决此问题的要点。它使用简化的 FetchXML 查询,但您会明白的。

      请注意在 Fetch 中添加了 top='2000'

      var fetchXml = @" <fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false' top='2000'>
                           <entity name='new_sampledata' />                                  
                         </fetch>";
      
      var result = svc.RetrieveMultiple(new FetchExpression(fetchXml));
      
      var entityRefs = result.Entities.Select(e=> e.ToEntityReference());
      
      //instead of e.ToEntityReference(), you'd use e.GetAttributeValue<EntityReference>("new_alterunitorderid")
      //like this:
      //var entityRefs = result.Entities.Select(e=> e.GetAttributeValue<EntityReference>("new_alterunitorderid"));
      
      var batchSize = 1000;
      var batchNum = 0;
      var numDeleted = 0;
      
      while (numDeleted < entityRefs.Count())
      {
          var multiReq = new ExecuteMultipleRequest()
          {
              Settings = new ExecuteMultipleSettings()
              {
                  ContinueOnError = false,
                  ReturnResponses = false
              },
              Requests = new OrganizationRequestCollection()
          };
      
          var currentList = entityRefs.Skip(batchSize * batchNum).Take(batchSize).ToList();
      
          currentList.ForEach(r => multiReq.Requests.Add(new DeleteRequest { Target = r }));
      
          svc.Execute(multiReq);
      
          numDeleted += currentList.Count;
          batchNum++;
      }
      

      【讨论】:

        【解决方案3】:

        FetchXML 有 5000 条记录的限制,我该如何绕过?

        答案是Paging cookie

        可以使用ExecuteMultipleRequest 进行批量删除。

        public static void BulkDelete(IOrganizationService service, DataCollection<EntityReference> entityReferences)
           {
               // Create an ExecuteMultipleRequest object.
               var multipleRequest = new ExecuteMultipleRequest()
               {
                   // Assign settings that define execution behavior: continue on error, return responses. 
                   Settings = new ExecuteMultipleSettings()
                   {
                       ContinueOnError = false,
                       ReturnResponses = true
                   },
                   // Create an empty organization request collection.
                   Requests = new OrganizationRequestCollection()
               };
        
               // Add a DeleteRequest for each entity to the request collection.
               foreach (var entityRef in entityReferences)
               {
                   DeleteRequest deleteRequest = new DeleteRequest { Target = entityRef };
                   multipleRequest.Requests.Add(deleteRequest);
               }
        
               // Execute all the requests in the request collection using a single web method call.
               ExecuteMultipleResponse multipleResponse = (ExecuteMultipleResponse)service.Execute(multipleRequest);
           }
        

        Reference

        【讨论】:

        • 该方法也有限制:“默认最大批量大小为 1000,这意味着使用此方法您一次只能创建/更新/删除最多 1000 条记录。”而且 ExecuteMultipleRequest 只能被调用两次或者抛出异常! msdn.microsoft.com/en-us/library/jj863631.aspx
        • @AlanJudi 是正确的。通常在插件或任何其他操作中,我们不需要超过这个容量。如果您在某些集成中执行此操作,是的,您必须在此容量范围内自己处理它,例如逐批进行..
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-15
        • 2019-03-14
        • 1970-01-01
        • 1970-01-01
        • 2021-05-25
        相关资源
        最近更新 更多