加载中

This tutorial will take you through your first NHibernate project, illustrating the basic steps required for configuration and mapping.

To keep things focused, we will begin with a very simple example to get you started.  And to keep the code to a minimum, we'll be putting aside unit tests and interface code, and focus exclusively on just enough code to persist our data and illustrate some basic CRUD (Change, Read, Update, Delete) techniques.    

The tools used in this and other examples include:

Microsoft SQL Server 2005 Express Edition - This will house our persistent data.  This tutorial will also work with SQL Server 2008.  For the purposes of our example, we will assume you have a local instance of SQL Server and are familiar with working with SQL Management Studio. 

NHibernate version 2.1.2 - You can download the latest version of NHibernate at the following link:  http://sourceforge.net/projects/nhibernate/files/NHibernate/

Microsoft Visual Studio 2008 - our development environment.

这篇教程将透过你的第一个NHibernate项目,讲述配置和映射所需要的基本步骤。

仅关注我们想要的,我们将从一个很简单的例子开始。为了让代码量最小,我们也去掉了单元测试和接口的代码,专一地关注持久化数据的代码并阐述一些基本的CRUD(Change, Read, Update, Delete) 技术。

这篇教程和其他样例中要用到的工具:

Microsoft SQL Server 2005 Express Edition - 存放我们的持久化数据。这篇教程在SQL Server 2008环境下也有效。在这篇教程中,我假设你有一个本地SQL Server的实例并且熟练地使用SQL Manger Studio。

NHibernate version 2.1.2 - 你可以点击下方链接下载最先的 NHibernate:  http://sourceforge.net/projects/nhibernate/files/NHibernate/

Microsoft Visual Studio 2008 - 我们的开发环境。


Creating our Project File

Since we're not going to be focusing on the user interface in this example, we will start by creating a new Console Application project:

For the purposes of this tutorial, we will be calling our application 'HelloNHibernate'.  I would recommend sticking to that naming convention and also following along with the various examples and names used, since in many cases these names may be used in other parts of the tutorial.

创建项目文件

在这个例子里,因为我们不关注用户界面 ,所以我们将从创建一个新的控制台应用程序项目开始:

根据这篇教程的目的,我们把我们的应用程序取名叫'HelloNHibernate'。我也推荐坚持这种命名的传统,并遵循不同的样例使用不同的名字,尽管在很多情形下,教程的其他部分也会使用这样的命名。 

Adding a reference to NHibernate

Our next step is to add a series of references needed for NHibernate to function effectively.  When you downloaded and extracted your NHibernate installation, several directories were created, including 'Required_bins' and 'Required_for_LazyLoading.

First, you will need to include all of the DLLs in Required Bins - these represent the core components used by NHibernate.

Next, we need to include all of the DLLs in one of the subfolders of Required_for_LazyLoading.  The choice of which set of DLLs you use for Lazy Loading is ultimately up to you, although for the purposes of this and other tutorials we will be using the Castle dynamic proxy.

 

添加对NHibernate的引用

我们下一步要添加一系列让NHibernate发挥作用的必须添加的引用。当你下载并解压你的NHibernate安装包后,电脑上就会创建一些目录,包括 'Required_bins'和'Required_for_LazyLoading。

首先,你要把 Required Bins目录下所有的DLL包含进来 - 它们代表NHibernate使用的核心组件。

其次,我们把Required_for_LazyLoading的一个子目录下所有的Dll包含进来。选择哪个目录的Dll来完成延迟加载,最终将取决于你。 在这篇教程和其他文章中,我使用的是Castle dynamic proxy。

Configuring NHibernate

With our references set up, we will now need to create and update our App.config (if this were a website, we would be modifying Web.config).  For our project, we are going to make a few assumptions:

  • We will be working with a local instance of SQL Server 2005 and have created our database.

  • We have a trusted connection to our database

  • We will be using the Castle proxy factory

  • We will be outputting our TSQL to the console (I strongly recommend this as you learn NHibernate, since it lets you see what it is doing under the hood).

Here is an example App.config containing just the pieces we will need for our tutorial.

<?xmlversion="1.0"encoding="utf-8" ?>

<configuration>

    <configSections>
        <sectionname="hibernate-configuration"requirePermission="false"type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
    </configSections>

    <hibernate-configurationxmlns="urn:nhibernate-configuration-2.2">
        <reflection-optimizeruse="false" />
        <session-factory>
            <propertyname="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
            <propertyname="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
            <propertyname="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
            <propertyname="connection.connection_string">Data Source=(local); Initial Catalog=quickstart; Trusted_Connection=true;</property>
            <propertyname='proxyfactory.factory_class'>NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
            <propertyname="show_sql">true</property>
        </session-factory>
    </hibernate-configuration>
</configuration>

You will see in our configuration that we are setting up NHibernate to use SQL Server and the SQL 2005 dialect for it's dynamic SQL.  You will also see our connection string (you can modify this as needed), our reference to the Castle Proxy Factory, and a flag (show_sql) telling NHibernate to output all TSQL statements to the console.

配置NHibernate

建立好我们的引用之后,我们现在需要创建和更新我们的App.config (如果是网站,就修改Web.config)。在我们的项目中,我做以下几个假设:

  • 我们安装了SQL Server 2005并创建好了数据库.

  • 数据库开启了信任连接

  • 使用Castle proxy factory

  • 把TSQL语句输出到控制台(在你学习NHibernate的时候,我强烈推荐你这样做,因为你可以看到后台正在做什么).

这是一个App.config配置的例子,它包含了这篇教程中所需要的部分。

<?xmlversion="1.0"encoding="utf-8" ?>

<configuration>

    <configSections>
        <sectionname="hibernate-configuration"requirePermission="false"type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
    </configSections>

    <hibernate-configurationxmlns="urn:nhibernate-configuration-2.2">
        <reflection-optimizeruse="false" />
        <session-factory>
            <propertyname="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
            <propertyname="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
            <propertyname="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
            <propertyname="connection.connection_string">Data Source=(local); Initial Catalog=quickstart; Trusted_Connection=true;</property>
            <propertyname='proxyfactory.factory_class'>NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
            <propertyname="show_sql">true</property>
        </session-factory>
    </hibernate-configuration>
</configuration>

在配置中,你将看到我们创建NHibernate来使用SQL Server和SQL 2005的语句。你也能看到连接字符串(可以根据需要修改),还有对Castle Proxy Factory的引用,也有一个告诉Nhibernate输出TSQL语句到控制台的标志(show_sql)。 

Creating our Model

NHibernate allows you to work directly with Plain Old CLR Objects (POCOs) instead of having to directly interact with the database via stored procedures.  One advantage of using POCOs is that we are not tied to a specific persistence layer.  For example, some ORM solutions require special attributes, or are based on your model objects inheriting from a specific base class. 

In the case of NHibernate, no special decoration is required to allow our objects to interact with our persistence layer.  The only concession we need to make for NHibernate is that all properties we wish to persist must be virtual, and if lazy loading is enabled, all public methods in our class must be virtual even if they are not included in our mapping file.

As a general rule of thumb, it's best to make all of your properties virtual, this way your bases are covered whether you use lazy loading or not.

创建我们的模型

NHibernate允许你直接使用Plain Old CLR Objects (POCOs),而不用通过存储程序来直接和数据库交互。使用POCOs的一个优势在于我们不用绑定特定的持久化层。举个例子,有些ORM解决方案需要特殊属性,或者是基于你的模型对象,这些对象又是从特定的基类中继承而来的。

在NHibernate中,不用特殊的修饰,就可以让我们的对象和持久化层交互。在NHibernate中,我们唯一要意识到的是所有的我们希望持久化的属性必须是虚拟的,并且要开启延迟加载,所有类中的公共方法必须是虚拟的,哪怕它们并没有包含到我们的映射文件中。

通常来讲,最好把所有的属性都设置为虚拟的,这样你的基类就封装了,不管你使用延迟加载与否。

Additionally, we can have properties and methods in our POCO that are not persisted, and can easily have multiple POCOs that map to the same table within our database.  For example, we may have one POCO that provides the complete detail screen of a product, including images and a comprehensive description, and another lightweight version that just includes the name and quantity that would be used to generate a product list.

For our tutorial, we will be creating an extremely simple object.  In the following tutorials, we will build upon this to cover more complex topics like parent/child relationships, advanced search techniques, etc. 

Create a new class in your project named 'Product' with the properties below.  Note that NHibernate is case sensitive, so our property names will need to exactly match our NHibernate mapping that we will be creating later.

namespace HelloNHibernate
{
    public classProduct
    {
        public virtual int? ProductId { get; set; }
        public virtual string ProductName { get; set; }
    }
}

Note that we've made the ProductId a nullable field.  This will allow us to create instances of this object without an ID, which in turn will tell NHibernate that this is a new object and not one that happens to have an ID of '0'.

另外,我们可以让POCO里的属性和方法不持久,并且可以让多个POCOs映射到数据库中相同的数据表。举个例子,我们有一个POCO提供了产品的详情,包括图片和描述,其他的轻量版本只包括用来创建商品清单的名称和数量。

在我们的教程中,我们将创建一个极端的简单对象。在后期的教程中,我们会讲述更加复杂的话题,比如父子关系,高级搜索技术等等。

创建在你的项目中创建一个类,命名为‘Produce’,并设置如下的属性。注意Nhibernate是大小写敏感的,所以我们的属性名要准确地匹配后面要创建的Nhibernate映射。

namespace HelloNHibernate
{
    public classProduct
    {
        public virtual int? ProductId { get; set; }
        public virtual string ProductName { get; set; }
    }
}

注意我们设置ProductId为可为null的值。这允许我们创建一个没有ID的实例,反过来告诉NHibernate这是一个新对象而不是一个ID为'0'的对象。

Creating our NHibernate Mapping File

Nhibernate uses XML mapping files to map between our POCO and our database objects.  While in many cases these may be a one to one relationship, this is not compulsory.  You can easily change field names, and create different maps to create alternate presentation views for your database object.

For example, we could have a complex 'Product' object that included a large blob of narrative text, and a collection of associated orders along with complex inventory data.  While this map would be excellent for a detailed product view where we are editing a single product, it would be way too heavy to use as a member of a strongly types list used in a dropdown of products.  In the latter case, we could create a much simpler map to a presentation view that only has the product ID and product name.

For our tutorial, we will be working with a very simple map that directly relates to the POCO we created above.  To create a map, add a new XML file to your project as shown below.  When creating the xml file, it should end with .hbm.xml - this convention tells NHibernate that this is a mapping file.  We will name ours 'Product.hbm.xml'

 

创建NHibernate映射文件

Nhibernate使用XML映射文件来映射POCO到数据库对象。虽然在很多案例中这可能是一对一关系,但这并不是必要的。你可以轻易地更改字段名称并创建不同的映射来给数据库对象创建可选的表示区域。

举个例子,我们有一个复杂的'Product'对象,它包含了大量的文本信息,一个与订单和复杂清单数据的容易。这对于我们正在编辑的单个产品的产品详情区域来说,将是一个很好的映射,它将变得十分臃肿,以至于在产品的下拉列表中,它不能作为一个强类型列表的成员。在后面,要创建一个更简单一点到只有产品ID和产品名称的持久化区域的映射。

在我们的教程中,我们使用一个简单的直接关系到我们上面创建的POCO的映射。来创建这样的一个映射,我们要添加一个新的XML文件到上面展示的工程中。当创建XML文件时,要让它以.hbm.xml命名方式结尾-这种传统告诉NHibernate这是一个映射文件。我们的名称叫做'Product.hbm.xml'。

Your XML mapping file should include the following information.  We will cover each of these tags below:
<?xmlversion="1.0"encoding="utf-8" ?>
<hibernate-mappingxmlns="urn:nhibernate-mapping-2.2"
                           assembly="HelloNHibernate"
                           namespace="HelloNHibernate">

    <class name="Product" table="Products">
        <id name="ProductId">
            <generatorclass="identity"/>
        </id>
        <property name="ProductName"length="50" />
    </class>
</hibernate-mapping>

  • Within the hibernate-maping tag, we're referencing both the assembly and namespace that the classes (POCOs) below reside in.  This is handy when your mapping files end up in a separate namespace or assembly than your model.

  • The class element represents our mapping to a single POCO.  The name represents the name of a class within the assembly and namespace from above, while the table attribute tells NHibernate which table or view in our database to map to

  • The id element tells NHibernate which database field and corresponding object property to use as a unique key.  In this case, we are using the ProductId field.

  • The generator element tells NHibernate how to create unique IDs for new entities.  Since we will be using the Identity attribute in SQL Server, we will specifiy the generator class as 'identity'.

  • The property tag is the tag you will see the most.  This simply maps a POCO property to the corresponding field in our table or view.  I've included the length attribute in our example since we will want to be able to generate a schema from this map, and the default of 255 characters is much larger than we will need for a product name.

你的XML文件应该包含以下信息。下面我们将一一讲述每一个标签:
<?xmlversion="1.0"encoding="utf-8" ?>
<hibernate-mappingxmlns="urn:nhibernate-mapping-2.2"
                           assembly="HelloNHibernate"
                           namespace="HelloNHibernate">

    <class name="Product" table="Products">
        <id name="ProductId">
            <generatorclass="identity"/>
        </id>
        <property name="ProductName"length="50" />
    </class>
</hibernate-mapping>
  • 在hibernate-maping标签中,我们同时引用类集(POCOs)所属的程序集合命名空间。当你的映射文件在单独的命名空间或者程序集而不是模型中,这种方式是十分方便的。

  • class元素表示到单个POCO的映射。name表示上面的程序集和命名空间中的类名,table属性告诉NHibernate数据库中的哪个表或者视图将被映射。

  • id元素告诉NHibernate哪个数据库的字段和对应的对象作为一个唯一键来使用。在本例子中,我们使用ProductId这个字段。

  • generator元素告诉NHibernate怎样给新实体来创建唯一ID。因为我们使用SQL Server属性中的ID属性,所以我们指明generator类为'identity'。

  • property标签是你见得最多的标签。它简单地映射一个到数据表或者视图中对应字段的映射。我已经把这个例子中最长的属性包含进来了,因为我们想为映射创建一个架构。对于我们所需要的产品名称,默认的255个字符已经足够大了。

Once your mapping file is created, you will need to make sure that you have it set as an embedded resource, otherwise NHibernate will be unable to read your XML file and mapping will not take place.  To do this, click on your new XML file in solution explorer, select properties, and change the Build Action for the XML file.

 

At this point, your solution should look like the solution shown below:

 

一旦XML文件创建好了,你需要确保它被设置为嵌入式资源,否则NHibernate不会读出你的XML文件,那么映射就不会生效了。完成这一步,你要在解决方案资源浏览器中点击你新建的XML文件,更改XML的生成方式。

 

到这一步,你的解决方案应该和下图类似:

 

Connecting to our database using NHibernate

At this point, we have completed our configuration and setup, and we are ready to begin interacting with our database using NHibernate. 

Throughout these examples, I would recommend following along and observing how your objects change, and also how data persists to the database.  This will help you better understand how NHibernate works, and help reinforce the examples below as you observe your persistent data changing.

Now, for the code!  It's very important to note that in this first example, we're focusing only on the minimal code needed to work with persistent data via NHibernate , and not focusing on testability and other best practices.  As we move into more complex examples, we will spend some time building a more robust architecture that will serve as a better starting point for your live applications.

Within NHibernate, our root object will be an object implementing the ISessionFactory interface.  a SessionFactory is a fairly expensive object, and you should only need one for your application.

使用 NHibernate连接数据库

到了这一步,我们已经完成了安装和配置,现在就准备使Nhibernate和我们的数据库来交互。

透过这些例子,我推荐你单独跟着做,并观察对象是如何发生改变的,数据又是如何持久化到数据库的。在你观察持久化对象改变的时候,这有助于你更好地理解NHibernate是如何工作的,有助于你巩固下面的样例。

下面到了代码了!在第一个样例中,我们只关注使用NHibernate来完成持久化数据所需要的最小量的代码,而不关注测试和其他更好的实践,注意到这些事很重要的。当我们引申到更复杂的样例中,我们要花费更多的时间为你的实际程序来创建运行更好的,更加健壮的架构。

在NHibernate中,我们的根对象将是一个实现ISessionFactory接口的对象。一个SessionFactory是一个很昂贵的对象,在你的程序中,你只有在需要一个就够了。

返回顶部
顶部
返回顶部
顶部