分为如下几层
Web
BLL
IDAL
Model
DALFactory
NHDAL
根据PetShop3.0的框架:Web层只依赖于BLL和Model,也就是说web层调用BLL层方法返回的Model层定义的数据;BLL层依赖于IDAL,Model,这一层实际是使用IDAL中的方法组合为业务,并处理IDAL层返回的Model;IDAL定义了所有底层方法,给DAL层留下接口;Model定义了对象实体,只有属性没有方法,基本上可以作为抽象类定义。DALFactory的作用是根据配置文件中的设置动态取出取出数据访问层(Data Access Layer)对象的实例,这样做就把实际使用的DAL跟BLL层分离,如果需要切换到其他DAL,只要修改此层就可以了。
本项目使用NH(NHibernate)作为DAl,所以命名为NHDAL。NHDAL依赖于Model,继承Model中属性的定义,并添加了NH需要用到的属性器。同时NHDAL实现IDAL中定义的方法。
下面是对登陆验证和储存日志的实例
先看看IDAL和Model中的定义吧
代码段一 IDAL接口定义
using
System;
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
namespace
CManager.IDAL.Log
![](https://i-blog.csdnimg.cn/blog_migrate/11b06a473f9facfb5d7b7a3a719538b0.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
/**//// <summary>
/// ILoginLog 的摘要说明。
/// </summary>
public interface ISignLog
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
void LogSignIn( string userid, string sessionid, string clientip, DateTime logindate );
![](https://i-blog.csdnimg.cn/blog_migrate/0b1fc21344d52d505643122ef48d59dd.gif)
bool CheckPassword( string userid, string password);
}
}
代码段二 Model对象定义
using
System;
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
namespace
CManager.Model.Log
![](https://i-blog.csdnimg.cn/blog_migrate/11b06a473f9facfb5d7b7a3a719538b0.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
/**//// <summary>
/// LoginInfo 的摘要说明。
/// </summary>
public class SignLogInfo
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
public int SignLogID
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return _SignLogID;}
}
public string UserID
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return _UserID;}
}
public string SessionID
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return _SessionID;}
}
public string ClientIP
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return _ClientIP;}
}
public DateTime SignInDate
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return _SignInDate;}
}
public DateTime SignOutDate
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return _SignOutDate;}
}
![](https://i-blog.csdnimg.cn/blog_migrate/0b1fc21344d52d505643122ef48d59dd.gif)
protected int _SignLogID;
protected string _UserID;
protected string _SessionID;
protected string _ClientIP;
protected DateTime _SignInDate;
protected DateTime _SignOutDate;
}
}
然后是BLL中调用。因为BLL不依赖于任何DAL,所以通过中间层DALFactory创建DAL的实例,并通过IDAl定义的接口返回给BLL。
代码段三 BLL方法
using
System;
using
System.Collections;
using
System.Web;
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
using
CManager.Model.Log;
using
CManager.Model.Collections;
using
CManager.DALFactory.Log;
using
CManager.IDAL.Log;
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
namespace
CManager.BLL.Log
![](https://i-blog.csdnimg.cn/blog_migrate/11b06a473f9facfb5d7b7a3a719538b0.gif)
{
public class Log
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/0b1fc21344d52d505643122ef48d59dd.gif)
//未完成,应该返回Module.Log.Account
public static bool Login ( string userid, string password, HttpContext context )
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
ISignLog log = LogFactory.CreateSignLog();
if (log.CheckPassword(userid,password))
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
log.LogSignIn( userid ,context.Session.SessionID, context.Request.UserHostAddress, DateTime.Now );
return true;
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
return false;
}
}
}
}
代码段四 DALFactory方法
using
System;
using
CManager.IDAL.Log;
using
System.Reflection;
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
namespace
CManager.DALFactory.Log
![](https://i-blog.csdnimg.cn/blog_migrate/11b06a473f9facfb5d7b7a3a719538b0.gif)
{
public class LogFactory
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
public static ISignLog CreateSignLog()
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
//获取web.config里DAL的设置
string path = System.Configuration.ConfigurationSettings.AppSettings["WebDAL"];
//组合出类名
string className = path + ".Log.SignLog";
//运行时创建类实例,需要类实现实例化
return (ISignLog) Assembly.Load(path).CreateInstance(className);
}
}
}
代码段五 web.config
<?
xml version="1.0" encoding="utf-8"
?>
<
configuration
>
<!--
这段大家都熟悉了
-->
<
configSections
>
<
section
name
="nhibernate"
type
="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089"
/>
</
configSections
>
<
nhibernate
>
<
add
key
="hibernate.connection.provider"
value
="NHibernate.Connection.DriverConnectionProvider"
/>
<
add
key
="hibernate.connection.driver_class"
value
="NHibernate.Driver.SqlClientDriver"
/>
<
add
key
="hibernate.connection.connection_string"
value
="server=127.0.0.1;database=CManager;uid=sa;pwd=;"
/>
<
add
key
="hibernate.connection.isolation"
value
="ReadCommitted"
/>
<
add
key
="hibernate.dialect"
value
="NHibernate.Dialect.MsSql2000Dialect"
/>
</
nhibernate
>
<
appSettings
>
<!--
默认显示每页显示记录数
-->
<
add
key
="DefaultRecordCount"
value
="20"
/>
<!--
*数据库层所在命名空间* 实际使用的DAL在这里设置
-->
<
add
key
="WebDAL"
value
="CManager.NHDAL"
/>
</
appSettings
>
<
system
.web
>
<!-- 这段按下,不占页面了 -->
</
system.web
>
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
</
configuration
>
理论上Web层并不知道IDAL层定义的原子方法,只使用BLL层给出的方法。这就是所谓的业务层与表现层分开。Web层只接受用户发出的请求,然后处理参数交给BLL层,并对BLL层返回的结果进行判断返回给结果。
代码段六 Web层调用
using
System;
using
System.Collections;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Web;
using
System.Web.SessionState;
using
System.Web.UI;
using
System.Web.UI.WebControls;
using
System.Web.UI.HtmlControls;
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
using
CManager.BLL.Log;
using
CManager.Model.Log;
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
namespace
BTTech.CManager.Web
![](https://i-blog.csdnimg.cn/blog_migrate/11b06a473f9facfb5d7b7a3a719538b0.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
/**//// <summary>
/// Login 的摘要说明。
/// </summary>
public class Login : PageBase
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
protected System.Web.UI.WebControls.TextBox UserName;
protected System.Web.UI.WebControls.TextBox Password;
protected System.Web.UI.HtmlControls.HtmlInputImage ImageButton1;
private void Page_Load(object sender, System.EventArgs e)
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
}
![](https://i-blog.csdnimg.cn/blog_migrate/0b1fc21344d52d505643122ef48d59dd.gif)
private void ImageButton1_ServerClick(object sender, System.Web.UI.ImageClickEventArgs e)
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
if (Log.Login( UserName.Text, Password.Text, this.Context))
Response.Redirect("",true);
else
Alert("用户名或密码错误");
}
}
}
最后是本文的主角NHDAL了,虽然最后出现,却是所有实际操作的最终执行者。
代码段七 实现IDAL
using
System;
using
NHibernate.Cfg;
using
NHibernate;
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
namespace
CManager.NHDAL.Log
![](https://i-blog.csdnimg.cn/blog_migrate/11b06a473f9facfb5d7b7a3a719538b0.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
/**//// <summary>
/// SignLog 的摘要说明。
/// </summary>
public class SignLog : NHObject,CManager.IDAL.Log.ISignLog
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
public SignLog()
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
}
![](https://i-blog.csdnimg.cn/blog_migrate/0b1fc21344d52d505643122ef48d59dd.gif)
public void LogSignIn(string userid, string sessionid, string clientip, DateTime logindate)
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
ISession session = CreateSession();
session.Save(new SignLogInfo(userid, sessionid, clientip, logindate));
}
![](https://i-blog.csdnimg.cn/blog_migrate/0b1fc21344d52d505643122ef48d59dd.gif)
public bool CheckPassword( string userid, string password)
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{//未完成
return true;
}
}
}
代码段八 继承Model
using
System;
using
CManager.Model;
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
namespace
CManager.NHDAL.Log
![](https://i-blog.csdnimg.cn/blog_migrate/11b06a473f9facfb5d7b7a3a719538b0.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
/**//// <summary>
/// SignLog 的摘要说明。
/// </summary>
public class SignLogInfo : CManager.Model.Log.SignLogInfo
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
private int Id
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return this._SignLogID;}
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
set
{this._SignLogID = value;}
}
private string NH_UserID
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return _UserID;}
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
set
{_UserID = value;}
}
private string NH_SessionID
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return _SessionID;}
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
set
{_SessionID = value;}
}
private string NH_ClientIP
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return _ClientIP;}
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
set
{_ClientIP = value;}
}
private DateTime NH_SignInDate
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return _SignInDate;}
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
set
{_SignInDate = value;}
}
private DateTime NH_SignOutDate
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
get
{return _SignOutDate;}
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
set
{_SignOutDate = value;}
}
![](https://i-blog.csdnimg.cn/blog_migrate/0b1fc21344d52d505643122ef48d59dd.gif)
private SignLogInfo()
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/0b1fc21344d52d505643122ef48d59dd.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/0b1fc21344d52d505643122ef48d59dd.gif)
internal SignLogInfo(string userid, string sessionid, string clientip, DateTime signdate )
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
this._UserID = userid;
this._SessionID = sessionid;
this._ClientIP = clientip;
this._SignInDate = signdate;
this._SignOutDate = signdate;
}
}
}
代码段九 影射文件 SignLogInfo.hbm.xml 这里用到上篇文章《不让NH属性器破坏封装》提到的方法
<?
xml version="1.0" encoding="utf-8"
?>
<
hibernate-mapping
xmlns
="urn:nhibernate-mapping-2.0"
>
<
class
name
="CManager.NHDAL.Log.SignLogInfo, CManager.NHDAL"
table
="CM_SignLog"
>
<
id
name
="Id"
type
="Int32"
unsaved-value
="0"
>
<
column
name
="SignLogID"
sql-type
="int"
not-null
="true"
unique
="true"
index
="PK__CM_SignLog__79A81403"
/>
<
generator
class
="native"
/>
</
id
>
<
property
name
="NH_UserID"
type
="String"
>
<
column
name
="UserID"
length
="50"
sql-type
="nvarchar"
not-null
="true"
/>
</
property
>
<
property
name
="NH_SessionID"
type
="String"
>
<
column
name
="SessionID"
length
="24"
sql-type
="nvarchar"
not-null
="true"
/>
</
property
>
<
property
name
="NH_ClientIP"
type
="String"
>
<
column
name
="ClientIP"
length
="20"
sql-type
="nvarchar"
not-null
="true"
/>
</
property
>
<
property
name
="NH_SignInDate"
type
="DateTime"
>
<
column
name
="SignInDate"
sql-type
="datetime"
not-null
="true"
/>
</
property
>
<
property
name
="NH_SignOutDate"
type
="DateTime"
>
<
column
name
="SignOutDate"
sql-type
="datetime"
not-null
="false"
/>
</
property
>
</
class
>
</
hibernate-mapping
>
代码段十 小技巧,NHObject基类
定义了一个NHObject的基类,因为任何实际操作对象is a NHObject,所以均继承这个类
这样做的好处是当我们需要更改加载连接字符串方法(比如解密)的时候只需在此出修改,还可以比较大面积地更改NH的使用方法。
using
System;
using
NHibernate;
using
NHibernate.Cfg;
![](https://i-blog.csdnimg.cn/blog_migrate/ee7f98e75435cd2371a21596930d865d.gif)
namespace
CManager.NHDAL
![](https://i-blog.csdnimg.cn/blog_migrate/11b06a473f9facfb5d7b7a3a719538b0.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
/**//// <summary>
/// NHConfigBase 的摘要说明。
/// </summary>
public class NHObject
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
private static Configuration config = new Configuration().AddAssembly(System.Reflection.Assembly.Load("CManager.NHDAL"));
private static ISessionFactory sessionFactory = config.BuildSessionFactory();
protected static NHibernate.ISession CreateSession()
![](https://i-blog.csdnimg.cn/blog_migrate/cb49b05a004a56b547ef86cf0d2f7174.gif)
{
return sessionFactory.OpenSession();
}
}
}
这样一个完整的框架就成功地搭建并运行了。:)