最近在学WCF,所以有两个设想疑问(菜鸟多疑问):
如果有WCF服务A,WCF服务B,客户端调用WCF服务A插入一条数据,然后再调用服务B也插入一条数据,然而服务B出错了进行了回滚,服务A能不能也进行回滚操作?
或是客户端调用服务A和服务B,成功了插入了两条数据之后,客户端这边出错了,如何让服务A和服务B插入的数据也回滚操作?
经过学习探索,了解到WCF支持分布式事务,事务可以在多个服务中传播,也可以在服务端与客户端之间传播。
注:WCF内并非所有绑定都支持事务的,常用的BasicHttpBinding就不支持事务的传播。只有以下几个绑定才能支持事务流的运转:NetTcpBinding、WSHttpBinding、WSDualHttpBinding、WSFederationHttpBinding、NetNamedPipeBinding。
代码尝试
先建一个WCF服务(WSHttpBinding),有两个Add方法,在客户端两次分开调用
[ServiceContract]public interfaceIService1
{
[OperationContract]string AddData_1(stringa);
[OperationContract]string AddData_2(stringa);
}
public classService1 : IService1
{
[OperationBehavior(TransactionScopeRequired= true, TransactionAutoComplete = true)]
[TransactionFlow(TransactionFlowOption.Allowed)]public string AddData_1(stringb)
{using (testEntities ts = newtestEntities())
{
Student a= newStudent()
{
Age= 9999999,
Class=b,
Sex= "男",
Score= 100};
ts.Student.Add(a);
ts.SaveChanges();
}return "22222";
}
[OperationBehavior(TransactionScopeRequired= true, TransactionAutoComplete = true)]
[TransactionFlow(TransactionFlowOption.Allowed)]public string AddData_2(stringb)
{using (testEntities ts = newtestEntities())
{
Student a= newStudent()
{
Age= 9999999,
Class=b,
Sex= "男",
Score= 100};
ts.Student.Add(a);
ts.SaveChanges();throw new Exception("出错拉!"); //抛出错误
}return "22222";
}
}
其中标红解释:
TransactionScopeRequired:值为true时,表示此WCF服务的方法中启动事务,为false,反之不启动。
TransactionAutoComplete:值为true时为隐式事务,方法在运行过程中没有抛出Exception,事务会自动提交。如果期间出现任何异常,事务就会自动回滚;false时,显式事务,必须OperationContext.Current.SetTransactionComplete () 显式提交事务。
TransactionFlowOption:设置为Allowed,开启事务传播,客户端的事务传播到服务端。
有三个值:
NotAllowed,禁止客户端传播事务流到服务端,即使客户端启动了事务,该事务也会被忽略;
Allowed,允许客户端的事务传播到服务端,但服务器端不一定会引用到此事务(如果服务端方法没开启事务);
Mandatory,服务端与客户端必须同时启动事务流,否则就会抛出InvalidOperationException异常。
web.config配置(重要)
服务端web.config
客户端
bindingConfiguration="WSHttpBinding_IService1" contract="TestService.IService1"name="WSHttpBinding_IService1">
客户端代码
情况一:WCF服务中的方法2报错回滚,那么之前第一次调用插入的是否成功回滚?
static void Main(string[] args)
{//客户端开启分布式事务,要引用System.Transactions.dll
using (TransactionScope ts = newTransactionScope())
{//调用服务
using (TestService.Service1Client service = newTestService.Service1Client())
{
service.AddData_1("1");
}
Console.WriteLine("第一次调用:成功插入一条数据");
//重新去调用WCF服务using (TestService.Service1Client service2 = newTestService.Service1Client())
{//WCF中的AddData_2会报错
service2.AddData_2("2");
}
ts.Complete();
}
}
结果:
WCF服务插入第二条数据,已经报错,因为该方法中已经设置 [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)],开启了事务,所以第二数据肯定是会被回滚的
且看第一条数据是否也会被回滚?,结果是两条数据都被回滚了
情况2:两次调用WCF服务成功插入数据后,客户端报错回滚,在WCF服务中插入的数据是否也回滚?
将抛出错误注释掉,重新运行WCF服务
改写客户端代码,并设下断点:
执行到断点,查看数据情况
已经成功插入,继续执行,由于没有进行提交,所以该事务将会自动回滚,且看在WCF服务中插入的数据是否会被回滚
客户端进行了回滚操作,很显然,客户端的事务传播的WCF中的方法事务,也将相应的操作回滚。