【发布时间】:2015-03-17 13:02:19
【问题描述】:
我有一个在执行某些操作的自定义实体的 Create(同步,操作后)上注册的 CRM 插件,我希望 Create 操作能够成功,尽管插件中存在错误。出于性能原因,我还希望插件在创建记录时立即触发,因此使插件异步是不可取的。我通过执行以下操作来实现这一点:
public class FooPlugin : IPlugin
{
public FooPlugin(string unsecureInfo, string secureInfo) { }
public void Execute(IServiceProvider serviceProvider)
{
try
{
// Boilerplate
var context = (IPluginExecutionContext) serviceProvider.GetService(typeof (IPluginExecutionContext));
var serviceFactory = (IOrganizationServiceFactory) serviceProvider.GetService(typeof (IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
// Additional validation omitted
var targetEntity = (Entity) context.InputParameters["Target"];
UpdateFrobber(service, (EntityReference)targetEntity["new_frobberid"]);
CreateFollowUpFlibber(service, targetEntity);
CloseTheEntity(service, targetEntity);
}
catch (Exception ex)
{
// Send an email but do not re-throw the exception
// because we don't want a failure to roll-back the transaction.
try
{
SendEmailForException(ex, context);
}
catch { }
}
}
}
但是,当发生错误时(例如在UpdateFrobber(...) 中),服务客户端会收到此异常:
System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]:
There is no active transaction. This error is usually caused by custom plug-ins
that ignore errors from service calls and continue processing.
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ref ProxyRpc rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(ref MessageData msgData, Int32 type)
at Microsoft.Xrm.Sdk.IOrganizationService.Create(Entity entity)
at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.CreateCore(Entity entity)
at Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.Create(Entity entity)
at Microsoft.Xrm.Client.Services.OrganizationService.<>c__DisplayClassd.<Create>b__c(IOrganizationService s)
at Microsoft.Xrm.Client.Services.OrganizationService.InnerOrganizationService.UsingService(Func`2 action)
at Microsoft.Xrm.Client.Services.OrganizationService.Create(Entity entity)
at MyClientCode() in MyClientCode.cs: line 100
我猜这是因为 UpdateFrobber(...) 使用从插件派生的 IOrganizationService 实例,因此它进行的任何 CRM 服务调用都参与与插件相同的事务,如果这些“子”操作失败,则会导致整个事务要回滚。它是否正确?是否有一种“安全”的方法可以忽略同步插件中“子”操作的错误?也许是一种实例化不重用插件上下文的 IOrganizationService 实例的方法?
如果相关,我们正在本地运行 CRM 2013。
【问题讨论】:
-
Caleb 你确定插件在那之后没有执行吗?我的意思是您的方法触发了另一个错误的插件,如果它是同步的,那么您正在查看的插件会因此而失败。为了防止这种情况发生,您可以将子插件移动到后期异步,或者您可以在子插件中管理异常。
标签: dynamics-crm dynamics-crm-2013