转眼一个星期过去了,还没有实际访问数据库,要加油了。
万丈高楼从地起,我们一步一步开始。
一. 准备数据
数据访问自然又要数据了,这里我们使用 《Microsoft SQL Server 2008技术内幕:T-SQL语言基础 》 一书中的示例数据库,这本书的详细介绍可以在这里找到。
非常好的一本书,其中的一些内容在别的地方是找不到的,比如查询的处理过程以及对 SQL Server 中锁的介绍等等,不幸的是书中提供的示例代码地址被墙了,我在博客园中上传了一份。
下载地址:https://files.cnblogs.com/haogj/TSQLFundamentals2008.rar
你必须已经安装了 SQL Server 2008,各种版本都可以,在查询分析器窗口中,直接执行下载的脚本,就可以完成数据库的创建了。完成之后的数据库如图所示。
下面我们将要访问其中的 Sales.Customers 表,这个表的结构如下:
二. 创建解决方案
打开 Visual Studio 2010, 创建一个新的网站项目。
1. 创建实体项目
在解决方案中,添加一个新的类库项目,这里命名为 Forbetter.Domain。
删除模板中自动添加的 Class1.cs, 在其中添加一个类文件 Customer.cs,修改其中的代码为如下内容。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Forbetter.Domain
{
public class Customer
{
public virtual int Id { get; private set; }
public virtual string CompanyName { get; set; }
public virtual string ContactName { get; set; }
public virtual string ContactTitle { get; set; }
public virtual string Address { get; set; }
public virtual string City { get; set; }
public virtual string Region { get; set; }
public virtual string PostalCode { get; set; }
public virtual string Country { get; set; }
public virtual string Phone { get; set; }
public virtual string Fax { get; set; }
}
}
以后,我们对数据库中 Customer 表的访问将通过这个类进行。
需要注意的是,其中的属性都使用 virtual 进行了修饰。这是 NHibernate 的要求。
为了表达这个类与关系之间的映射关系,在 NHibernate 中需要定义对象关系映射,映射的方式有多种,最常见的是使用 xml 配置文件。
在项目中增加一个名为 Customer.hbm.xml 的 xml 文件,这个文件的扩展名必须为 hbm.xml。以后, NHibernate 可以自动寻找这种扩展名的文件来寻找映射关系。
在属性窗口中,将这个文件的生成操作设置为:嵌入的资源,这样这个文件将会被编译器嵌入到生成的 dll 文件中。
这个文件的内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Forbetter.Domain">
<class name="Forbetter.Domain.Customer" table="Sales.Customers" lazy="false" >
<id name="Id" unsaved-value="null" column="custid" type="int" >
<generator class="identity" />
</id>
<property name="CompanyName" column="CompanyName" length="40" not-null="true" index="CompanyName"/>
<property name="ContactName" length="30" not-null="false"/>
<property name="ContactTitle" length="30" not-null="false"/>
<property name="Address" length="60" not-null="false"/>
<property name="City" length="15" not-null="false" index="City"/>
<property name="Region" length="15" not-null="false" index="Region"/>
<property name="PostalCode" length="10" not-null="false" index="PostalCode"/>
<property name="Country" type="String" length="15" not-null="false"/>
<property name="Phone" length="24" not-null="false"/>
<property name="Fax" length="24" not-null="false"/>
</class>
</hibernate-mapping>
现在,这个项目的内容应该如下。
2. 创建数据访问项目
在解决方案中添加第三个项目,
项目中需要添加对 Forbetter.Domain 的引用。
这里开始使用 NHibernate 了,为项目添加 NHibernate 的引用。这里涉及到两个程序集:NHibernate.dll 和 Iesi.Collectionss.dll,在项目中还使用了 Spring.NET 的特性,所以还需要添加对 Spring.Core.dll 的引用。
总共会有四个程序集的引用。
在这个项目中添加一个文件夹 Config,然后,在其中增加一个 xml 文件,命名为 dataAccess.xml。这个文件的生成属性,也需要定义为嵌入的资源,其中的内容如下:
<?xml version="1.0" ?>
<objects xmlns="http://www.springframework.net"
xmlns:db="http://www.springframework.net/database"
xmlns:tx="http://www.springframework.net/tx"
>
<!--描述-->
<description>
数据访问的配置信息
包括:DbProvider
NHibernate
</description>
<!-- 通过主应用程序的上下文配置文件引用 -->
<object type="Spring.Objects.Factory.Config.PropertyPlaceholderConfigurer, Spring.Core">
<property name="ConfigSections" value="spring/databaseSettings"/>
</object>
<!-- 数据库的配置 -->
<db:provider id="DbProvider"
provider="SqlServer-2.0"
connectionString="Data Source=${db.server};Database=${db.database};Integrated Security=true;"
/>
<!-- NHibernate 配置 -->
<!-- 可以通过 name 为其指定别名 name="SessionFactory" -->
<object id="NHibernateSessionFactory"
type="Spring.Data.NHibernate.LocalSessionFactoryObject,Spring.Data.NHibernate32"
>
<!-- 关于数据库连接的配置,直接使用 DbProvider 中的设置,这样,不需要为 Hibernate 再提供连接串和驱动 -->
<property name="DbProvider" ref="DbProvider"/>
<!-- 包含有映射文件的程序集,需要分析的hbm程序集名称 -->
<property name="MappingAssemblies">
<list>
<value>Forbetter.Domain</value>
</list>
</property>
<!-- 其他的参数 -->
<property name="HibernateProperties">
<dictionary>
<!-- 方言 -->
<entry key="dialect" value="NHibernate.Dialect.MsSql2008Dialect"/>
<entry key="use_proxy_validator" value="false" />
<entry key="show_sql" value="true"/>
</dictionary>
</property>
<!-- 必须增加此项说明,与 Spring 的声明式事务集成 -->
<property name="ExposeTransactionAwareSessionFactory" value="true" />
</object>
</objects>
这里需要的注意的是,在数据库连接串中,使用了类似 ${db.server} 的方式,这里的 db.server 是定义在配置文件中变量名,我们将会在主程序的配置文件中定义这些变量,在这里通过名称来使用。以后需要修改数据库连接信息的时候,就可以不同找到这个配置文件,而直接在主程序的配置文件中进行修改就可以了。
第二个文件中,定义了使用 NHibernate 访问数据库的接口,由于在所有的 Dao 对象中都需要通过 SessionFactory 来访问当前的会话对象,定义了接口 INHibernateSessionFactory。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Forbetter.Dao
{
interface INHibernateSessionFactory
{
NHibernate.ISessionFactory SessionFactory { set; get; }
}
}
然后,增加第三个文件, ICustomerDao.cs,这是一个接口定义文件,在 Spring.NET 中通过接口来耦合各个部分,这也是 Spring.NET 代理的特点。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Forbetter.Dao
{
public interface ICustomerDao
{
IQueryable<Domain.Customer> GetAllCustomers();
}
}
第四个文件为 CustomerDao.cs,实现这两个接口。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Linq;
namespace Forbetter.Dao
{
[Spring.Stereotype.Repository]
public class CustomerDao
: ICustomerDao, INHibernateSessionFactory
{
// Nhibernate 会话支持
public NHibernate.ISessionFactory SessionFactory { set; get; }
public IQueryable<Domain.Customer> GetAllCustomers()
{
NHibernate.ISession session = this.SessionFactory.GetCurrentSession();
var query = session.Query<Domain.Customer>();
var result = from customer in query
orderby customer.CompanyName
select customer;
return result;
}
}
}
其中 SessionFactory 下面使用 Spring.NET 的方式进行注入。
添加第五个文件,objects.xml,在这里使用 Spring.NET 的方式定义数据访问对象,并进行注入。注意生成方式也需要为嵌入的资源。
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
<object id="CustomerDaoImpl" type="ForBetter.Dao.CustomerDao, ForBetter.Dao" >
<!-- ref 表示引用的对象 -->
<property name="SessionFactory" ref="NHibernateSessionFactory" />
</object>
</objects>
现在,这个项目已经完成了,编译一下。项目中的内容应当如下所示:
3. 添加服务项目
通常我们还需要一个业务层,这里我们创建一个 Service 项目来表示一下。
这个项目需要引用的内容会多一些,包括 Domain 项目,Dao 项目,以及 Spring.NET 的三个程序集。Spring.Core, Spring.Data, Spring.Aop。
在项目中同样定义一个服务接口。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Forbetter.Service
{
public interface ICustomerService
{
Forbetter.Dao.ICustomerDao CustomerDao { set; get; }
IList<Domain.Customer> GetAllCustomers();
}
}
然后是服务的实现。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Forbetter.Service
{
[Spring.Stereotype.Service]
[Spring.Transaction.Interceptor.Transaction(ReadOnly=true)]
public class CustomerService
:ICustomerService
{
public Forbetter.Dao.ICustomerDao CustomerDao { set; get; }
public IList<Domain.Customer> GetAllCustomers()
{
IQueryable<Domain.Customer> query = this.CustomerDao.GetAllCustomers();
return query.ToList<Domain.Customer>();
}
}
}
在项目中添加一个名为 Config 的文件夹,在其中添加一个对象定义文件 objects.xml。
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
<object id="CustomerServiceImpl" type="Forbetter.Service.CustomerService" >
<!-- ref 表示引用的对象 -->
<property name="CustomerDao" ref="CustomerDaoImpl" />
</object>
</objects>
完成之后的项目内容如下所示。
4. 定义 Web 项目
终于可以使用 Spring.NET 和 NHibernate 的成果了。Web 项目我们一开始已经创建了,现在需要增加一些内容。
首先,需要添加许多引用,包括对服务项目的引用,对 Domain 项目的引用,对 NHibernate 和 Spring.NET 的引用。还有日志的引用。
注意使用了 Spring.Data.NHibernate32,这是 Spring.NET 对 NHibernate 的支持。
在项目中,添加一个名为 Customer 的文件夹,我们管理客户信息的页面将会保存在这里。
在文件夹中,添加一个标准的 aspx 页面,名为 index.aspx。页面内容如下,定义了一个 GridView 来显示数据。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="index.aspx.cs" Inherits="Sprint_Web_1.Customer.index" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView runat="server" ID="gvCustomer"></asp:GridView>
</div>
</form>
</body>
</html>
将代码文件修改为如下内容。这里使用我们在服务项目中定义的 CustomerService 来访问数据。属性将会通过 Spring.NET 进行注入,这里直接调用服务的方法来获取客户对象的列表。然后通过页面上的 GridView 显示出来。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Sprint_Web_1.Customer
{
public partial class index : System.Web.UI.Page
{
public Forbetter.Service.ICustomerService CustomerService { set; get; }
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
IList<Forbetter.Domain.Customer> list = this.CustomerService.GetAllCustomers();
this.gvCustomer.DataSource = list;
this.gvCustomer.DataBind();
}
}
}
}
在项目中也添加一个 Config 的文件夹。
先添加一个名为 objects.xml 的文件,定义对象注入。
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net">
<object type="~/Customer/index.aspx">
<property name="CustomerService" ref="CustomerServiceImpl"/>
</object>
</objects>
然后添加日志配置文件 log4net.xml。这次我们通过 log4net 将日志输出到 Trace 窗口中。
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<root>
<level value="OFF" />
<appender-ref ref="TraceAppender" />
</root>
<logger name="NHibernate">
<level value="DEBUG" />
</logger>
<appender name="TraceAppender" type="log4net.Appender.TraceAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger %ndc - %message%newline" />
</layout>
</appender>
</log4net>
最后,也是最重要的是 web 项目的根配置文件 web.config ,这是最重要的一个配置文件。
<?xml version="1.0" encoding="utf-8"?>
<!--
有关如何配置 ASP.NET 应用程序的详细消息,请访问
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<configSections>
<!-- Spring 的配置 -->
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web"/>
<!-- 数据库的配置参数 -->
<section name="databaseSettings" type="System.Configuration.NameValueSectionHandler"/>
</sectionGroup>
<!-- 日志配置 -->
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="~/Config/objects.xml"/>
<!-- 嵌入在程序集中的配置文件 ,首先是程序集名称,然后命名空间,最后文件名, 注意名称的大小写必须完全一致 -->
<resource uri="assembly://Forbetter.Dao/Forbetter.Dao.Config/dataAccess.xml"/>
<resource uri="assembly://Forbetter.Dao/Forbetter.Dao.Config/objects.xml"/>
<resource uri="assembly://Forbetter.Service/Forbetter.Service.Config/objects.xml"/>
</context>
<!--数据库配置服务器地址-->
<databaseSettings>
<add key="db.server" value=".\sqlexpress"/>
<add key="db.database" value="TSQLFundamentals2008"/>
<add key="db.userid" value=""/>
<add key="db.password" value=""/>
</databaseSettings>
</spring>
<common>
<logging>
<factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4Net">
<!-- 使用 log4net 配置文件 -->
<arg key="configType" value="FILE-WATCH" />
<arg key="configFile" value="~/Config/log4net.xml" />
</factoryAdapter>
</logging>
</common>
<appSettings>
<!-- 为 OpenSessionInViewModule 的 SessionFactory 提供名字 -->
<add key="Spring.Data.NHibernate.Support.OpenSessionInViewModule.SessionFactoryObjectName" value="NHibernateSessionFactory"/>
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<httpModules>
<!-- Spring 提供的 Module -->
<add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
<!--
由 Spring 自动打开会话,必须提供一个名为 SessionFactory 的会话工厂
使用后,可以使用 SessionFactory 的 GetCurrentSession 方法获取会话
-->
<add name="OpenSessionInView"
type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate32"/>
</httpModules>
<httpHandlers>
<!-- Spring 提供的处理程序 -->
<add verb="*" path="*.aspx" type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
<!-- 取消 Spring.NET 对于 Web 服务的处理 -->
<!--<add verb="*" path="*.asmx" type="Spring.Web.Services.WebServiceHandlerFactory, Spring.Web"/>-->
<add verb="*" path="ContextMonitor.ashx" type="Spring.Web.Support.ContextMonitor, Spring.Web"/>
<add verb="*" path="*.ashx" type="Spring.Web.Support.DefaultHandlerFactory, Spring.Web"/>
</httpHandlers>
</system.web>
</configuration>
文件的内容已经增加了注释进行说明。
三. 源代码下载
文件比较大,博客园限制最大为 10M, 所以分为了两个文件。
整个项目的源代码可以从这里下载: