【IT168 技术应用】我们已实现了在同一应用程序下的分布式事务——即多Dao层+同Service层,每个Dao对应一个数据库,一个Service调用多个Dao。但是在一些特定的子系统较多的项目中,开发人员是无法访问到某个子系统的数据库,这就意味着不能通过增加Dao层来实现分布式事务。正如一个银行的软件系统,记录了客户的账户信息和存款金额,北京的分公司和上海的分公司分别有自己的数据库和软件系统。现在,要实现北京的系统向上海的系统转账,然而各自作为开发人员来说,没有足够的权限去访问对方的数据库,但是可以提供Web Service的方式去访问其系统服务。这样,我们就需要实现基于Web Service的分布式事务。
实现基于Web Service的分布式事务的方法比较多,可以通过.NET企业服务的方式。但是为了更好的实现,我们选择WCF作为一个分布式应用程序框架。WCF在实现分布式事务中有它的优越之处。其思路在于启动MSDTC服务,将客户端的事务以流的方式传递到服务器端,在服务器端执行通过时,客户端再提交事务,相反则回滚事务。
我们模仿上篇的场景做一个demo,并使用上篇的Dao和Domain。
一、启动MSDTC服务。
二、Service层
①.Customer
public interface ICustomerManager
{
CustomerInfo Get(object id);
object Save(CustomerInfo entity);
void Update(CustomerInfo entity);
}
public class CustomerManager : ICustomerManager
{
private ICustomerDao Dao { get; set; }
public CustomerInfo Get(object id)
{
return Dao.Get(id);
}
public object Save(CustomerInfo entity)
{
return Dao.Save(entity);
}
public void Update(CustomerInfo entity)
{
if (entity.Money > 3000)
{
throw new Exception("订金上限");
}
Dao.Update(entity);
}
}
{
CustomerInfo Get(object id);
object Save(CustomerInfo entity);
void Update(CustomerInfo entity);
}
public class CustomerManager : ICustomerManager
{
private ICustomerDao Dao { get; set; }
public CustomerInfo Get(object id)
{
return Dao.Get(id);
}
public object Save(CustomerInfo entity)
{
return Dao.Save(entity);
}
public void Update(CustomerInfo entity)
{
if (entity.Money > 3000)
{
throw new Exception("订金上限");
}
Dao.Update(entity);
}
}
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
<object id="transactionManager"
type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate21">
<property name="DbProvider" ref="DbProvider"/>
<property name="SessionFactory" ref="NHibernateSessionFactory"/>
</object>
<object id="transactionInterceptor" type="Spring.Transaction.Interceptor.TransactionInterceptor, Spring.Data">
<property name="TransactionManager" ref="transactionManager"/>
<property name="TransactionAttributeSource">
<object type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource, Spring.Data"/>
</property>
</object>
<object id="BaseTransactionManager" type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data" abstract="true">
<property name="PlatformTransactionManager" ref="transactionManager"/>
<property name="TransactionAttributes">
<name-values>
<add key="*" value="PROPAGATION_REQUIRED"/>
</name-values>
</property>
</object>
<object id="Customer.CustomerManager" parent="BaseTransactionManager">
<property name="Target">
<object type="Customer.Service.Implement.CustomerManager, Customer.Service">
<property name="Dao" ref="Customer.CustomerDao"/>
</object>
</property>
</object>
</objects>
<objects xmlns="http://www.springframework.net">
<object id="transactionManager"
type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate21">
<property name="DbProvider" ref="DbProvider"/>
<property name="SessionFactory" ref="NHibernateSessionFactory"/>
</object>
<object id="transactionInterceptor" type="Spring.Transaction.Interceptor.TransactionInterceptor, Spring.Data">
<property name="TransactionManager" ref="transactionManager"/>
<property name="TransactionAttributeSource">
<object type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource, Spring.Data"/>
</property>
</object>
<object id="BaseTransactionManager" type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data" abstract="true">
<property name="PlatformTransactionManager" ref="transactionManager"/>
<property name="TransactionAttributes">
<name-values>
<add key="*" value="PROPAGATION_REQUIRED"/>
</name-values>
</property>
</object>
<object id="Customer.CustomerManager" parent="BaseTransactionManager">
<property name="Target">
<object type="Customer.Service.Implement.CustomerManager, Customer.Service">
<property name="Dao" ref="Customer.CustomerDao"/>
</object>
</property>
</object>
</objects>
②.Order
public interface IOrderManager
{
object Save(OrderInfo entity);
}
public class OrderManager : IOrderManager
{
public IOrderDao Dao { get; set; }
public object Save(OrderInfo entity)
{
return Dao.Save(entity);
}
}
{
object Save(OrderInfo entity);
}
public class OrderManager : IOrderManager
{
public IOrderDao Dao { get; set; }
public object Save(OrderInfo entity)
{
return Dao.Save(entity);
}
}
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
<object id="transactionManager"
type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate21">
<property name="DbProvider" ref="DbProvider"/>
<property name="SessionFactory" ref="NHibernateSessionFactory"/>
</object>
<object id="transactionInterceptor" type="Spring.Transaction.Interceptor.TransactionInterceptor, Spring.Data">
<property name="TransactionManager" ref="transactionManager"/>
<property name="TransactionAttributeSource">
<object type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource, Spring.Data"/>
</property>
</object>
<object id="BaseTransactionManager" type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data" abstract="true">
<property name="PlatformTransactionManager" ref="transactionManager"/>
<property name="TransactionAttributes">
<name-values>
<add key="*" value="PROPAGATION_REQUIRED"/>
</name-values>
</property>
</object>
<object id="Order.OrderManager" parent="BaseTransactionManager">
<property name="Target">
<object type="Order.Service.Implement.OrderManager, Order.Service">
<property name="Dao" ref="Order.OrderDao"/>
</object>
</property>
</object>
</objects>
<objects xmlns="http://www.springframework.net">
<object id="transactionManager"
type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate21">
<property name="DbProvider" ref="DbProvider"/>
<property name="SessionFactory" ref="NHibernateSessionFactory"/>
</object>
<object id="transactionInterceptor" type="Spring.Transaction.Interceptor.TransactionInterceptor, Spring.Data">
<property name="TransactionManager" ref="transactionManager"/>
<property name="TransactionAttributeSource">
<object type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource, Spring.Data"/>
</property>
</object>
<object id="BaseTransactionManager" type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data" abstract="true">
<property name="PlatformTransactionManager" ref="transactionManager"/>
<property name="TransactionAttributes">
<name-values>
<add key="*" value="PROPAGATION_REQUIRED"/>
</name-values>
</property>
</object>
<object id="Order.OrderManager" parent="BaseTransactionManager">
<property name="Target">
<object type="Order.Service.Implement.OrderManager, Order.Service">
<property name="Dao" ref="Order.OrderDao"/>
</object>
</property>
</object>
</objects>