首页 > 编程开发 > Objective-C编程 >
-
坚持学习WF17 WF中的补偿
一:事务是你在做一组更新时要不成功,要不失败,不可能只部分更新。事务最经典的使用场合就是在关系型数据库中。补偿是取消之前已经成功的操作,在我们的工作流中我们可能完成一项任务有很多活动组成,比如我们的活动都使用了TransactionScopeActivity,我们在之后发现错误了,想要取消之前成功的操作,这个和事务就没有关系了,因为事务已经成功了。这个时候我们就可以使用补偿。你可以逻辑上划分一组活动,指定一个补偿处理器给这组活动。在补偿处理器中你声明如果补偿成功了就执行该组活动。补偿处理器就会自动跟踪异常了。或者我们直接使用CompensateActivity。
事务能自动做回滚操作,而补偿却不能,补偿只是提供了一个地方给你做取消的工作,但具体的代码就要你自己实现了。WF实现了ICompensatableActivity接口的可以有补偿的功能。WF自己提供了两个CompensatableTransactionScopeActivity
,CompensatableSequenceActivity。前一个活动支持事务和补偿。CompensatableHandlerActivity是你执行补偿的容器。你也可以明确的使用CompensateActivity,该活动允许你使用其TargetActivityName来指定对某个活动使用补偿。不过该活动只能被加到CompensationHandleActivity,FaultHandlerActivity,CancellationHandlerActivity中。
二:下面以一个具体的例子来说明补偿是如果使用的,假如你计划要去旅游,那么你在出发前会先定火车票,然后在定酒店。那么如果你定到火车票了,可是当你去定酒店的时候你发现所有的酒店都已经被别人预定了,这个时候你定的火车票也没有用了,只好退订了。在我们的程序中我们用补偿来完成这个功能。下图是我们设计的工作流:
我们的流程是这样的,首先预定火车票,然后在预定酒店,在预定酒店的时候我们会判断是否成功。如果不成功我们会抛出一个异常。在预定火车票活动(BookTicket)放到了CompensatableTransactionScopeActivity活动中,其中的补偿处理我们执行退订火车票的程序,如下图:
在预定酒店的时候,如果预定不成功我们会使用上图中的BookFail(ThrowActivity)活动来抛出一个异常,下面是我们自定义的一个异常类,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace CaryCompensationDemo
{
[SerializableAttribute()]
public class BookHotelException : Exception
{
public BookHotelException() : base()
{ }
public BookHotelException(string message) : base(message)
{ }
public BookHotelException(string message, Exception innerException) : base(message, innerException)
{ }
protected BookHotelException(SerializationInfo info, StreamingContext context) : base(info, context)
{ }
}
}
在整个工作的错误处理程序中来捕获异常,并执行补偿处理,如下图:
我们使用CompensateActivity活动的TargetActivityName属性来指定对某个活动使用补偿。整个工作流的代码如下:
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace CaryCompensationDemo
{
public sealed partial class CaryTourWorkflow: SequentialWorkflowActivity
{
public BookHotelException discontinuedProductException1 = new BookHotelException();
public CaryTourWorkflow()
{
InitializeComponent();
}
private void TourStart_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("准备去旅游咯");
}
private void BookTicket_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("预定火车票");
}
private void CancelTicket_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("退火车票");
}
private void BookHotelOK_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("酒店预定成功");
}
private void BookOk_Condition(object sender, ConditionalEventArgs e)
{
e.Result = false;
}
private void BookHotelException_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("没定到酒店");
}
}
}
三:使用补偿我们需要在宿主程序中加载持久化服务,下面是宿主程序的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
namespace CaryCompensationDemo
{
class Program
{
static AutoResetEvent waitHandle = new AutoResetEvent(false);
static void Main()
{
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
try
{
const string connectString = "Initial Catalog=workflowpersistence;
Data Source=localhost;Integrated Security=SSPI;";
workflowRuntime.AddService(new SqlWorkflowPersistenceService(connectString));
workflowRuntime.WorkflowCompleted += OnWorkflowCompleted;
workflowRuntime.WorkflowTerminated += OnWorkflowTerminated;
workflowRuntime.WorkflowAborted += OnWorkflowAborted;
workflowRuntime.StartRuntime();
Type type = typeof(CaryCompensationDemo.CaryTourWorkflow);
workflowRuntime.CreateWorkflow(type).Start();
waitHandle.WaitOne();
}
catch (Exception ex)
{
if (ex.InnerException != null)
Console.WriteLine(ex.InnerException.Message);
else
Console.WriteLine(ex.Message);
}
finally
{
workflowRuntime.StopRuntime();
}
}
}
static void OnWorkflowAborted(object sender, WorkflowEventArgs e)
{
Console.WriteLine("请检查数据库连接是否异常");
waitHandle.Set();
}
static void OnWorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
{
Console.WriteLine("完成工作流");
waitHandle.Set();
}
static void OnWorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
}
}
}
四:最后我们看下运行结果吧:
我们的流程是这样的,首先预定火车票,然后在预定酒店,在预定酒店的时候我们会判断是否成功。如果不成功我们会抛出一个异常。在预定火车票活动(BookTicket)放到了CompensatableTransactionScopeActivity活动中,其中的补偿处理我们执行退订火车票的程序,如下图:
在预定酒店的时候,如果预定不成功我们会使用上图中的BookFail(ThrowActivity)活动来抛出一个异常,下面是我们自定义的一个异常类,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace CaryCompensationDemo
{
[SerializableAttribute()]
public class BookHotelException : Exception
{
public BookHotelException() : base()
{ }
public BookHotelException(string message) : base(message)
{ }
public BookHotelException(string message, Exception innerException) : base(message, innerException)
{ }
protected BookHotelException(SerializationInfo info, StreamingContext context) : base(info, context)
{ }
}
}
在整个工作的错误处理程序中来捕获异常,并执行补偿处理,如下图: