我编写了一个插件,该插件通过fetchXML获取GUID ID,并使用Batch Delete批量删除1000条记录。
我调试了插件,它显示插件一直执行到service.RetrieveMultiple(new FetchExpression(fetchxml))
,但是,获取的记录没有被删除。有人可以解释为什么吗?这是插件代码:
using System;
using System.Linq;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Query;
/// <summary>
/// This plugin will trimm off unit orders after a contract is cancelled before the end of the contract duration
/// </summary>
namespace DCWIMS.Plugins
{
[CrmPluginRegistration(MessageNameEnum.Update,
"contract",
StageEnum.PostOperation,
ExecutionModeEnum.Asynchronous,
"statecode",
"Post-Update On Cancel Contract",
1000,
IsolationModeEnum.Sandbox,
Image1Name = "PreImage",
Image1Type = ImageTypeEnum.PreImage,
Image1Attributes = "")]
public class UnitPluginOnCancel : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// Extract the tracing service for use in debugging sandboxed plug-ins.
// Will be registering this plugin, thus will need to add tracing service related code.
ITracingService tracing = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
//obtain execution context from service provider.
IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));
// Output Parameters collection contains all the data passed in the message request.
if (context.InputParameters.Contains("Target") &&
context.InputParameters["Target"] is Entity)
{
Entity entity = (Entity)context.InputParameters["Target"];
//Get the before image of the updated contract
Entity PreImage = context.PreEntityImages["PreImage"];
//verify that target entity is contract and contains a cancellation date
if (entity.LogicalName != "contract" || entity.GetAttributeValue<OptionSetValue>("statecode").Value != 4)
return;
if (PreImage.GetAttributeValue<OptionSetValue>("statecode").Value == 0 || entity.Contains("cancelon"))
return;
if (PreImage.GetAttributeValue<OptionSetValue>("statecode").Value == 3 || PreImage.GetAttributeValue<OptionSetValue>("statecode").Value == 1)
return;
//obtain the organization service for web service calls.
IOrganizationServiceFactory serviceFactory =
(IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
//Core Plugin code in Try Block
try
{
//Get Contract line start date
var startDate = PreImage.GetAttributeValue<DateTime>("cancelon");
//Get Contract Line End Date
DateTime endDate = (DateTime)PreImage["expireson"];
//Get Contract range into weekdays list
Eachday range = new Eachday();
var weekdays = range.WeekDay(startDate, endDate);
//Get Unit Order Lookup Id
EntityReference unitOrder = (EntityReference)PreImage.Attributes["new_unitorderid"];
var unitOrders = service.Retrieve(unitOrder.LogicalName, unitOrder.Id, new ColumnSet("new_name"));
var unitOrdersId = unitOrders.Id;
var uiName = unitOrders.GetAttributeValue<string>("new_name");
//Get Entity Collection to delete
string fetchXml = @" <fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false' top='2000'>
<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.ToString("yyyy-MM-dd") + @"' />
<condition attribute='new_orderdate' operator='on-or-before' value='" + endDate.ToString("yyyy-MM-dd") + @"' />
<condition attribute='new_orderlineid' operator='eq' uiname='" + uiName + @"' uitype='new_units' value='" + unitOrdersId + @"' />
</filter>
</link-entity>
</entity>
</fetch>";
var result = service.RetrieveMultiple(new FetchExpression(fetchXml));
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 }));
service.Execute(multiReq);
numDeleted += currentList.Count;
batchNum++;
}
}
catch (FaultException<OrganizationServiceFault> ex)
{
throw new InvalidPluginExecutionException("An error occured.. Phil is responsible. ", ex);
}
catch (Exception ex)
{
tracing.Trace("An error occured: {0}", ex.ToString());
throw;
}
}
}
}
}
我尝试过:
var entityGuids = result.Entities.Select(ent => ent.GetAttributeValue<Guid>("new_alterunitorderid"));
var entityRefs = entityGuids.Select(guid => new EntityReference("new_alterunitorder", guid));
知道了:
答案 0 :(得分:2)
我认为错误是在您执行RetrieveMultiple
请求之后立即出现的
var entityRefs = result.Entities.Select(e => e.GetAttributeValue<EntityReference>("new_alterunitorderid"));
new_alterunitorderid
不是EntityReference
。这是主键。
代替尝试:
var entityRefs = result.Entities.Select(e => e.ToEntityReference());
您还应该利用tracing
对象在跟踪日志中包含更多输出:
tracing.Trace("Executing query");
var result = service.RetrieveMultiple(new FetchExpression(fetchXml));
tracing.Trace("{0} results found. Converting to EntityReferences", result.Entities.Count);
var entityRefs = result.Entities.Select(e => e.ToEntityReference());
答案 1 :(得分:1)
通常,批处理作业是异步的。进入设置>系统作业。搜索您的删除作业。我从未使用过这种特定的语法,但是逻辑似乎还可以。