使用Spring.Net+NHibernate構建WCF應用
在企業級應用開發中,利用合適的框架針對不同項目構建相應的應用。Spring.Net作為Spring的.Net版本,具有很強大的應用。如:作為IoC容器、AOP處理框架、與NHibernate的集成、Spring.Net發布WebService\WCF服務等。而NHibernate作為一個優秀的ORM框架也廣受開發者的青睞。本文將通過Spring.Net+NHibernate來構建WCF應用。
先上一張結構圖:
正式介紹之前介紹一下框架 版本:
Spring.Net :1.3.2
NHibernate :3.2(目前Spring支持的NHibernate最高版本)
1、Spring.Net與NHibernate的集成應用
Spring.Net以及NHibernate的配置:
Spring.Net對NHibernate支持的配置(配置1):
<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
2 <objects xmlns="http://www.springframework.net" xmlns:db="http://www.springframework.net/database">
3
4 <db:provider id="dbProvider" provider="SqlServer-1.1" connectionString="Data Source=.\SqlExpress;Initial Catalog=SpringNHibernateCourseSystem;Integrated Security=True"></db:provider>
5 <object id="NHibernateSessionFactory" type="Spring.Data.NHibernate.LocalSessionFactoryObject,Spring.Data.NHibernate32">
6 <property name="DbProvider" ref="dbProvider"></property>
7 <property name="MappingAssemblies">
8 <list>
9 <value>Domain</value>
10 </list>
11 </property>
12 <property name="HibernateProperties">
13 <dictionary>
14 <entry key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"></entry>
15 <entry key="dialect" value="NHibernate.Dialect.MsSql2005Dialect"></entry>
16 <entry key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"></entry>
17 <entry key="use_out_join" value="true"></entry>
18 <entry key="show_sql" value="true"></entry>
19 <entry key="hbm2ddl.auto" value="update"></entry>
20 <entry key="adonet.batch_size" value="10"></entry>
21 <entry key="command_timeout" value="10"></entry>
22 <entry key="cache.use_second_level_cache" value="true"></entry>
23 <entry key="cache.use_query_cache" value="true"></entry>
24 <entry key="query.substitutions" value="true 1, false 0, yes 'Y', no 'N"></entry>
25 </dictionary>
26 </property>
27 <property name="ExposeTransactionAwareSessionFactory" value="true"></property>
28 </object>
29
30 <object id="HibernateTemplate" type="Spring.Data.NHibernate.Generic.HibernateTemplate">
31 <property name="SessionFactory" ref="NHibernateSessionFactory"></property>
32 <property name="TemplateFlushMode" value="Auto"></property>
33 <property name="CacheQueries" value="true"></property>
34 </object>
35
注意:在此配置中,<resource >節點引用其他程序集下的配置(同NHibernate的映射文件一樣,被設置為"嵌入的資源"),請注意uri屬性的配置方式。
NHibernate映射的配置(配置3):
Spring.Net與NHibernate整合后的持久化操作如下:
{
#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> 集成子HibernateDaoSupport進行注入。如上配置2中的
<property name="HibernateTemplate" ref="HibernateTemplate"></property> </object>
注意:在Spring.Net的配置中,對泛型類型中的"<"的配置是通過<配置的,因為Spring.Net會認為"<" 是小于號。而對">"則沒有此類要求。
2、Spring.Net注入WCF
上一篇中已經介紹了Spring.Net對WCF支持以及客戶端如何調用服務,本文不再做細致的介紹,只提幾點需要注意的地方:
View Code
注意:service name="classService" 的配置中,name不再需要服務類的名稱,而是用Spring.Net對服務配置的id即可。
服務寄宿:
{
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>();
.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 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對象來進行對象的持久化操作。注入如下:
<property name="Manager" ref="classManager"></property>
</object>
客戶端調用:
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

浙公網安備 33010602011771號