好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

使用Spring.Net+NHibernate构建WCF应用

使用Spring.Net+NHibernate构建WCF应用

使用Spring.Net+NHibernate构建WCF应用

 

在企业级应用开发中,利用合适的框架针对不同项目构建相应的应用。Spring.Net作为Spring的.Net版本,具有很强大的应用。如:作为IoC容器、AOP处理框架、与NHibernate的集成、Spring.Net发布WebService\WCF服务等。而NHibernate作为一个优秀的ORM框架也广受开发者的青睐。本文将通过Spring.Net+NHibernate来构建WCF应用。

本文要点: Spring.Net与NHibernate的集成应用 Spring.Net注入WCF Entity与DTO对象之间的转化 

先上一张结构图:

 

正式介绍之前介绍一下框架 版本:

NHibernate :3.2(目前Spring支持的NHibernate最高版本) 

 1、 Spring.Net与NHibernate的集成应用

Spring.Net以及NHibernate的配置:

Spring.Net对NHibernate支持的配置(配置1):

<? xml version="1.0" encoding="utf-8"  ?>
< objects  xmlns ="http://www.springframework.net"  xmlns:db ="http://www.springframework.net/database" >
    <!--配置数据库信息-->
     < db:provider  id ="dbProvider"  provider ="SqlServer-1.1"  connectionString ="Data Source=.\SqlExpress;Initial Catalog=SpringNHibernateCourseSystem;Integrated Security=True" ></ db:provider >
     < object  id ="NHibernateSessionFactory"  type ="Spring.Data.NHibernate.LocalSessionFactoryObject,Spring.Data.NHibernate32" >
         < property  name ="DbProvider"  ref ="dbProvider" ></ property >
         <!--配置NHibernate使用的实体程序集-- >  
< property  name ="MappingAssemblies" >
             < list >
                 < value > Domain </ value >
             </ list >
         </ property >
         <!--配置NHibernate的配置信息-- >   
< property  name ="HibernateProperties" >
             < dictionary >
                 < entry  key ="hibernate.connection.provider"  value ="NHibernate.Connection.DriverConnectionProvider" ></ entry >
                 < entry  key ="dialect"  value ="NHibernate.Dialect.MsSql2005Dialect" ></ entry >
                 < entry  key ="hibernate.connection.driver_class"  value ="NHibernate.Driver.SqlClientDriver" ></ entry >
                 < entry  key ="use_out_join"  value ="true" ></ entry >
                 < entry  key ="show_sql"  value ="true" ></ entry >
                 < entry  key ="hbm2ddl.auto"  value ="update" ></ entry >
                 < entry  key ="adonet.batch_size"  value ="10" ></ entry >
                 < entry  key ="command_timeout"  value ="10" ></ entry >
                 < entry  key ="cache.use_second_level_cache"  value ="true" ></ entry >
                 < entry  key ="cache.use_query_cache"  value ="true" ></ entry >
                 < entry  key ="query.substitutions"  value ="true 1, false 0, yes 'Y', no 'N" ></ entry >
             </ dictionary >
         </ property >
         < property  name ="ExposeTransactionAwareSessionFactory"  value ="true" ></ property >
     </ object >

     < object  id ="HibernateTemplate"  type ="Spring.Data.NHibernate.Generic.HibernateTemplate" >
         < property  name ="SessionFactory"  ref ="NHibernateSessionFactory" ></ property >
         < property  name ="TemplateFlushMode"  value ="Auto" ></ property >
         < property  name ="CacheQueries"  value ="true" ></ property >
     </ object >    
</ objects >  

Spring.Net自身的配置(配置2):

View Code 

注意:在此配置中,<resource >节点引用其他程序集下的配置(同NHibernate的映射文件一样,被设置为"嵌入的资源"),请注意uri属性的配置方式。

NHibernate映射的配置(配置3):

<!--StudentEntity.hbm.xml 文件-->

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain">

<class name="StudentEntity" table="`Student`">

<id name="Id" type="Int32" >

<column name="ID" length="4" sql-type="int" not-null="true" unique="true" index="PK_Student"/>

<generator class="native" />

</id>

<property name="Name" type="String">

<column name="Name" length="50" sql-type="nvarchar" not-null="false"/>

</property>

<property name="Sex" type="String">

<column name="Sex" length="1" sql-type="char" not-null="false"/>

</property>

<many-to-one name="Class" class="ClassEntity " >

<column name="ClassId" length="4" sql-type="int" not-null="false"/>

</many-to-one>

</class>

</hibernate-mapping>

 

<!--ClassEntity.hbm.xml 文件-->

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain">

<class name="ClassEntity" table="`Class`">

<id name="Id" type="Int32">

<column name="ID" length="4" sql-type="int" not-null="true" unique="true" index="PK_Class"/>

<generator class="native" />

</id>

<property name="Name" type="String" length="50">

<column name="Name" length="50" sql-type="varchar" not-null="false"/>

</property>

<bag name="Students" inverse="true" lazy="true" cascade="all">

<key column="ClassID" foreign-key="FK_Student_Class"/>

<one-to-many class="StudentEntity"/>

</bag>

</class>

</hibernate-mapping>

Spring.Net与NHibernate整合后的持久化操作如下:

       public class RepositoryBase < T >  : HibernateDaoSupport, IRepository < T >  where T : class  

    {
        #region IRepository < T >  成员

        public object Add(T entity)
        {
            return HibernateTemplate.Save(entity);
        }

        public void Delete(T entity)
        {
            HibernateTemplate.Delete(entity);
        }

        public void Update(T entity)
        {
            HibernateTemplate.Save(entity);
        }

        public T Get(int Id)
        {
            return HibernateTemplate.Get < T > (Id);
        }

        #endregion
    }

在Spring.Net中我们可以通过对RepositoryBase < T > 集成子Hibernate Dao Support进行注入。如上配置2中的

< object  id ="classRepository"  type ="DAO.Implement.RepositoryBase&lt;Domain.ClassEntity>,DAO" >
         < property  name ="HibernateTemplate"  ref ="HibernateTemplate" ></ property > </ object >

注意:在Spring.Net的配置中,对泛型类型中的"<"的配置是通过&lt;配置的,因为Spring.Net会认为"<" 是小于号。而对">"则没有此类要求。

2、 Spring.Net注入WCF  

上一篇 中已经介绍了Spring.Net对WCF支持以及客户端如何调用服务,本文不再做细致的介绍,只提几点需要注意的地方:

View Code  

注意:service name="classService"  的配置中,name不再需要服务类的名称,而是用Spring.Net对服务配置的id即可。

服务寄宿:

 static void Main(string[] args)  

{            
    ContextRegistry.GetContext();
    Console.WriteLine("Service Running...");
    Console.ReadLine();
}

  

3、 Entity与DTO对象之间的转化 

在NHibernate的应用中,一般是通过实体操作其映射的数据库表。因此此实体为不可或缺的。但通过应用层的逻辑处理后,展示给UI的可能是从不同的表中获取的信息,而UI层也不应用做一些业务处理;再者,如果将NHibernate使用的实体作为DTO也很可能面临传输了大量UI不需要的信息。所以想通过NHibernate的实体作为DTO(Data Transmit Object)肯定不是一种理想的方式。这样就面临一个问题:NHibernate的 Entity与DTO对象间如何转化? 
通过 Client传输过来的DTO对象给Entity对象赋值肯定可行,但是这种类似"体力活"的方式显然不应该推崇。这里,我使用的是轻量、开源的AutoMapper。

Mapper.CreateMap < StudentDTO , StudentEntity > ();

            Mapper.CreateMap < ClassDTO , ClassEntity > ()
                .ForMember(item => item.Name, mapping => mapping.MapFrom(item => item.NO))
                .ForMember(item=>item.Students,mapping=>mapping.MapFrom(item=>item.StudentDtos);
            ClassEntity entity = Mapper.Map < ClassDTO , ClassEntity > (@class);
            return Manager.Add(entity);

 此外:通过还可以已通过Mapper.AssertConfigurationIsValid()来检验Entity与DTO之间映射是否正确。

 服务操作:

     

     public class ClassService : IContracts  

    {
        public IClassManager Manager { get; set; }

        #region IContracts 成员

        public object Add(ClassDTO @class)
        {
            Mapper.CreateMap < StudentDTO , StudentEntity > ();
            Mapper.CreateMap < ClassDTO , ClassEntity > ()
                .ForMember(item => item.Name, mapping => mapping.MapFrom(item => item.NO))
                .ForMember(item=>item.Students,mapping=>mapping.MapFrom(item=>item.StudentDtos);
            ClassEntity entity = Mapper.Map < ClassDTO , ClassEntity > (@class);
            return Manager.Add(entity);
        }

        #endregion
    }

同样,我也是通过 对服务类中的 Manager属性进行注入,最终通过从IoC容器获取Manager对象来进行对象的持久化操作。注入如下:

< object  id ="classService"  type ="Services.ClassService,Services" >
                 < property  name ="Manager"  ref ="classManager" ></ property >
</ object >

 客户端调用:

IApplicationContext context = ContextRegistry.GetContext();  

var  proxy = context.GetObject( " classService " )  as  IContracts;

var  dto =  new  ClassDTO { NO =  " 035102A "  };
List<StudentDTO> studentDtoList =  new  List<StudentDTO>()
                {
                     new  StudentDTO{Name= " StudentA " ,Sex= 1 },
                     new  StudentDTO{Name= " StudentB " ,Sex= 0 },
                };
dto.StudentDtos = studentDtoList;
proxy.Add(dto);
(proxy  as  ICommunicationObject).Abort():

 结果:

 

题外: 

不知道大家有没有碰到过:有时调试程序时,添加的断点有时会出现 "当前没有命中断点,还没有为该文档加载任何符号" 。下图:

 在调试时可能出上述的调试过程中的问题:如下图:

 

 我通过实践发现,这是由于引用的此程序集(程序集A)的目标程序集(程序集B)中,可能由于生成时过程中,新生成程序集A没有被拷贝到程序集B。导致这次问题的产生。若果程序集B所引用的为程序集A最新版本,则调试会是能正常进行的。如下图:

 

 代码下载: http://download.csdn.net/detail/tyb1222/4425673

 

分类:  NHibernate ,  Spring.Net ,  WCF应用

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于使用Spring.Net+NHibernate构建WCF应用的详细内容...

  阅读:40次