• Spring.NET 1.3.2 集成 NHibernate 3.2 4 实现基本的数据访问


     转眼一个星期过去了,还没有实际访问数据库,要加油了。

    万丈高楼从地起,我们一步一步开始。

    一. 准备数据

    数据访问自然又要数据了,这里我们使用 《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, 所以分为了两个文件。

    整个项目的源代码可以从这里下载:

    项目文件1

    项目文件2

  • 相关阅读:
    The path "" is not valid path to the gcc binary.
    ADB命令介绍
    Android 中Message,MessageQueue,Looper,Handler详解+实例
    Sqlite 修改字段
    曾经光辉岁月 永远海阔天空
    用AchartEngineActivity引擎自定义图表控件和背景折线图
    一个帖子学会Android开发四大组件
    Android获得系统时间(24小时制)
    TagBuilder
    MVC
  • 原文地址:https://www.cnblogs.com/haogj/p/2623155.html
Copyright © 2020-2023  润新知