技术开发 频道

.NET实用技巧—NHibernate分布式事务

  三、服务契约和Host。

  1、契约

  作为服务契约,需要启用Session,并且设置TransactionFlowOption的等级为Allowed或Mandatory来接收客户端事务流。

  作为契约的实现部分,需要设置TransactionScopeRequired为true来启用事务作用域。

  ①.Customer

[ServiceContract(SessionMode = SessionMode.Required)]
    
public interface ICustomerContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
        CustomerInfo
Get(object id);

        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
        
object Save(CustomerInfo entity);

        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
        void Update(CustomerInfo entity);
    }

    [AspNetCompatibilityRequirements(RequirementsMode
= AspNetCompatibilityRequirementsMode.Required)]
    
public class CustomerServer : ICustomerContract
    {
        
public ICustomerManager Manager { get; set; }

        [OperationBehavior(TransactionScopeRequired
= true)]
        
public CustomerInfo Get(object id)
        {
            return Manager.Get(id);
        }

        [OperationBehavior(TransactionScopeRequired
= true)]
        
public object Save(CustomerInfo entity)
        {

            return Manager.Save(entity);
        }

        [OperationBehavior(TransactionScopeRequired
= true)]
        
public void Update(CustomerInfo entity)
        {
            Manager.Update(entity);
        }

   ②.Order

[ServiceContract(SessionMode = SessionMode.Required)]
    
public interface IOrderContract
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Allowed)]
        
object Save(OrderInfo entity);
    }

   [AspNetCompatibilityRequirements(RequirementsMode
= AspNetCompatibilityRequirementsMode.Required)]
    
public class OrderServer : IOrderContract
    {
        
public IOrderManager Manager { get; set; }

        [OperationBehavior(TransactionScopeRequired
= true)]
        
public object Save(OrderInfo entity)
        {
            return Manager.Save(entity);
        }
    }


   2、配置

  然而,Spring.NET针对NHibernate的Session管理使用的是OSIV模式(Open Session In View),即使用httpModule去拦截HTTP请求,在每次请求开始时打开Session作用域(SessionScope),最后在请求结束后关闭SessionScope。这样一来,在客户端每请求一次时都会打开SessionScope,在请求结束会关闭SessionScope,然后当请求结束后再去处理分布式就会提示“无法使用已释放对象”的错误。所以说,OSIV是无法正常管理分布式事务的。出于上述原因,我们决定在Global.asax的配置,在Session(这里的Session是ASP.NET中的Session)启动时候打开SessionScope,在Session结束时关闭SessionScope。这样分布式事务就会与SessionScope同步了。

  最后,在配置appSettings节点增加

  另外配置WCF的binding时需要选择一种支持Session的binding(如wsHttpBinding)并且将binding中的transactionFlow属性设置为true。

public class Global : System.Web.HttpApplication
    {

        protected void Application_Start(
object sender, EventArgs e)
        {
            log4net.Config.XmlConfigurator.Configure();
        }

        protected void Session_Start(
object sender, EventArgs e)
        {
            SessionScope sessionScope
= new SessionScope("appSettings", typeof(SessionScope), false);
            sessionScope.Open();
            HttpContext.Current.Session[
"SessionScope"] = sessionScope;
        }

        
        protected void Session_End(
object sender, EventArgs e)
        {
            SessionScope sessionScope
= HttpContext.Current.Session["SessionScope"] as SessionScope;
            
if (sessionScope != null)
            {
                sessionScope.Close();
            }
        }

    }

   ①.Customer

<?xml version="1.0" encoding="utf-8"?>
<configuration>

  
<%@ ServiceHost Language="C#" Debug="true" Service="Customer.Host" Factory="Spring.ServiceModel.Activation.ServiceHostFactory"%>

 

0
相关文章