NHibernate+WCF项目实战
第一篇、项目介绍与搭建;
第二篇、使用NHibernate实现数据访问并进行单元测试;
第三篇、使用WCF对外提供Webservices接口并进行单元测试;
第四篇、使用WAS对Webservices接口进行压力测试。
开发环境
我的开发环境是VS2008 SP1+SQLServer 2005
NHibernate版本是2.1.0.4000
NUnit版本是2.5.2
Microsoft Web Application Stress Tool 版本是1.1
本节概要
上一篇已经搭建了包含6个项目的解决方案,本节主要完成实体层和数据访问层的开发工作,同时使用NUnit对数据访问层中的方法进行单元测试。
准备工作
学习NHibernate
1)推荐系列文章:NHibernate之旅。
2)博客园也刚刚成立了NHibernate专题。
您可以先从sourceforge下载本项目需要的NHibernate程序集。下载以后Required_Bins下面是必须的程序集。Required_For_LazyLoading下面是延迟加载的三种方案所需的程序集。
开发Model
using
添加对NHibernate.dll的引用。
O/R Mapping
Model层主要是解决O/R Mapping。
R:我们在上一篇文章中已经建立了表UserInfo。
O:创建UserInfo对应的实体,UserInfo.cs。
using System;
using System.Collections.Generic;
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
namespace Lee.Model
{
///
<
summary
>
///
///
</
summary
>
[
Serializable
]
public
class UserInfo
{
public
UserInfo()
{
m_Id
=
0
;
m_Name
=
null
;
m_Description
=
null
;
m_State
=
null
;
}
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
private
int
m_Id;
private string m_Name;
private string m_Description;
private string m_State;
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
///<
summary
>
///
///</
summary
>
public
virtual
int
Id
{
get {
return
m_Id; }
set
{ m_Id
=
value; }
}
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
///<
summary
>
///
///</
summary
>
public
virtual string Name
{
get {
return
m_Name; }
set
{ m_Name
=
value; }
}
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
///<
summary
>
///
///</
summary
>
public
virtual string Description
{
get {
return
m_Description; }
set
{ m_Description
=
value; }
}
///<
summary
>
///
///</
summary
>
public
virtual string State
{
get {
return
m_State; }
set
{ m_State
=
value; }
}
}
}
Mapping:创建映射文件UserInfo.hbm.xml,并设置为嵌入的资源和始终复制。
<?
xml version="1.0" encoding="utf-8"
?>
<
hibernate-mapping
xmlns
="urn:nhibernate-mapping-2.2"
>
<
class
name
="Lee.Model.UserInfo, Lee.Model"
table
="UserInfo"
>
<
id
name
="Id"
column
="id"
type
="Int32"
unsaved-value
="0"
>
<
generator
class
="native"
/>
</
id
>
<
property
name
="Name"
type
="String"
column
="name "
/>
<
property
name
="Description"
type
="String"
column
="description "
/>
<
property
name
="State"
type
="String"
column
="state "
/>
</
class
>
</
hibernate-mapping
>
开发DAL
using
添加对NHibernate.dll的引用。
添加对Lee.Model项目的引用。
创建NHibernate的Session辅助类,SessionFactory。
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
NHibernate;
using
NHibernate.Cfg;
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
namespace
Lee.DAL
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
{
public class SessionFactory
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
private static ISessionFactory _factory;
private static object obj = new object();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
public ISession Session
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
get
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
if (_factory == null)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
lock (obj)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
if (_factory == null)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
Configuration cfg = new Configuration().Configure();
_factory = cfg.BuildSessionFactory();
}
}
}
return _factory.OpenSession();
}
}
}
}
不知道NHibernate中Session怎么用的请系统学习我推荐地址的文章。我在这里就不做重复介绍了!
创建UserInfo的数据访问类UserInfoDAL
主要定义了三个方法:添加用户、修改用户信息和检查用户是否存在。
这三个方法也是WCF将要对外提供的用户操作方法,考虑到删除操作的特殊性,不对外提供删除接口。
下面是UserInfoDAL的代码:
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
Lee.Model;
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
using
NHibernate.Cfg;
using
NHibernate;
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
namespace
Lee.DAL
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
{
public class UserInfoDAL
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
private ISession _session;
private SessionFactory _sessionfactory = new SessionFactory();
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
/// 添加用户
/// </summary>
/// <param name="name">用户名称</param>
/// <param name="description">用户描述</param>
/// <param name="state">状态</param>
/// <returns>True-操作成功|False-操作失败</returns>
public bool AddUserInfo(string name, string description,string state)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
if (!ExistUserInfo(name))
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
UserInfo userinfo = new UserInfo
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
Name = name,
Description = description,
State = state
};
using (_session = _sessionfactory.Session)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
_session.Save(userinfo);
_session.Flush();
}
return true;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
return false;
}
}
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
/// 检查用户是否存在
/// </summary>
/// <param name="name">用户名称</param>
/// <returns>True-用户存在|False-用户不存在</returns>
public bool ExistUserInfo(string name)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
bool result = false;
string hql = "select count(*) from UserInfo where Name=:name";
using (_session = _sessionfactory.Session)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
IQuery query = _session.CreateQuery(hql);
query.SetString("name", name);
result = (int.Parse(query.UniqueResult().ToString()) == 0) ? false : true;
}
return result;
}
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
/// 更新用户信息
/// </summary>
/// <param name="name">用户名称</param>
/// <param name="description">用户描述</param>
/// <param name="state">状态</param>
/// <returns>True-操作成功|False-操作失败</returns>
public bool UpdateUserInfo(string name, string description, string state)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
bool result = false;
if (ExistUserInfo(name))
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
string hql = "update UserInfo set Description=:description,State=:state where Name=:name";
using (_session = _sessionfactory.Session)
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
IQuery query = _session.CreateQuery(hql);
query.SetString("name", name);
query.SetString("description", description);
query.SetString("state", state);
result = (query.ExecuteUpdate() > 0) ? true : false;
}
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
result = false;
}
return result;
}
}
}
到这里我们已经完成了实体层和数据访问层的开发工作,下面我们用NUnit进行单元测试。
单元测试
安装NUnit
下载:http://www.nunit.org/index.php?p=download
using
添加对NHibernate.dll的引用。
添加对NHibernate.ByteCode.Castle的引用。
添加对nunit.framework的引用。
添加对Lee.Model项目的引用。
添加对Lee.DAL项目的引用。
copy以下程序集到/Lee.Test/bin/Debug下
NHibernate.dll
NHibernate.ByteCode.Castle.dll
Antlr3.Runtime.dll
Iesi.Collections.dll
log4net.dll
Castle.DynamicProxy2.dll
Castle.Core.dll
测试步骤
1)创建NHibernate配置文件hibernate.cfg.xml并设置为始终复制。
<?
xml version="1.0" encoding="utf-8"
?>
<
hibernate-configuration
xmlns
='urn:nhibernate-configuration-2.2'
>
<
session-factory
>
<
property
name
="show_sql"
>
true
</
property
>
<
property
name
="dialect"
>
NHibernate.Dialect.MsSql2005Dialect
</
property
>
<
property
name
="connection.driver_class"
>
NHibernate.Driver.SqlClientDriver
</
property
>
<
property
name
="proxyfactory.factory_class"
>
NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
</
property
>
<
property
name
="connection.connection_string_name"
>
SQLConnection
</
property
>
<
mapping
assembly
="Lee.Model"
/>
</
session-factory
>
</
hibernate-configuration
>
你需要自己配置以下节点:
数据库连接
<property name="connection.connection_string_name">SQLConnection</property>
mapping
<mapping assembly="Lee.Model"/>
2)创建应用程序配置文件App.config,设置数据库连接。
<?
xml version="1.0" encoding="utf-8"
?>
<
configuration
>
<
connectionStrings
>
<
add
name
="SQLConnection"
connectionString
="Database=XX;User ID=sa;Password=saas;Server=XX;"
providerName
="System.Data.SqlClient"
/>
</
connectionStrings
>
</
configuration
>
3)创建测试类TestUserInfoDAL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
using Lee.Model;
using Lee.DAL;
using NUnit.Framework;
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
namespace Lee.Test
{
[TestFixture]
public class TestUserInfoDAL
{
[Test]
public void AddUserInfo()
{
UserInfoDAL dal = new UserInfoDAL();
bool result = dal.AddUserInfo("testname4", "testdesc", "teststate");
Assert.AreEqual(true, result);
}
[Test]
public void ExistUserInfo()
{
UserInfoDAL dal = new UserInfoDAL();
bool result = dal.ExistUserInfo("testname");
Assert.AreEqual(true, result);
}
[Test]
public void UpdateUserInfo()
{
UserInfoDAL dal = new UserInfoDAL();
bool result = dal.UpdateUserInfo("testname", "hello,testname!", "activation");
Assert.AreEqual(true, result);
}
}
}
4)设置项目 Lee.Test调试时启动NUnit。
![](https://i-blog.csdnimg.cn/blog_migrate/4ec616ebe8a4739303b57d5186754316.jpeg)
5)设置该项目为启动项目,在测试方法中设置断点,项目启动后,会开启NUnit。
![](https://i-blog.csdnimg.cn/blog_migrate/281ca163abe0956bcaf6bca194345628.jpeg)
选择要测试的方法,Run即可单步调试程序了!
如果程序出现异常或者断言结果不相等(Assert.AreEqual)会出现红色进度条。 进度条下面有异常提示。
![](https://i-blog.csdnimg.cn/blog_migrate/c064fad6755a2796439deb1fe1685221.jpeg)
如果程序成功执行,当然就是一片绿了。
![](https://i-blog.csdnimg.cn/blog_migrate/d087e8e5a2e0897dcbbf45d1e561e1e3.jpeg)