NHibernate in action翻译——第二章 2.1节 Nhibernate的“Hello World”
2.1 Nhibernate的“Hello World”
NHibernate应用程序定义了持久化类来个数据库表关联。我们的“Hello World”示例包括一个类和一个匹配文件。让我们看一下持久化类和匹配文件是怎么样的和看一下我们可以对持久化类做些什么。
2.1.1 安装NHibernate
在你开始编写“Hello World”程序之前,你必须首先安装NHibernate,然后创建一个解决方案去包含它。
NHibernate1.2.1GA可以在http://www.nhforge.org/下载。点击“download”标签,定位到“NHibernate Core”在这里你可以下载NHibernate 1.2.1.GA.msi文件。
虽然这本书市委NHibernate1.2.1.GA写的,但是我们也知道很多人已经在使用NHibernate 2.0 Beta。因此,我们提供适用于两个版本的技术。
一旦你下载安装了NHibernate,你就可以开始适用它了。
2.1.2 创建一个项目
对于这个项目,你应该用Visual Studio创建一个空的项目。这是一个简单的应用程序,因此,最简单的方法是去创建一个C#的控制台应用程序。命名项目为HelloNhibernate。你也可以使用VB.NET来创建项目,但是在这本书中,我们选择用C#来做例子。
程序需要用到NHibernate的类库,因此,下一步需要添加引用到这个项目中:
1、 右击项目,选择添加引用。
2、 点击浏览标签,导航到NHibernate的安装目录。默认的,NHibernate安装在C:\Program Files\NHibernate\bin\net2.0\目录下。
3、 从引用列表中,选择NHibernate.dll。点击OK去添加引用到你的项目中。
默认的,控制台应用程序应该添加了一个叫Program.cs的文件到你的解决方案中。打开这个文件。
4、 在Program.cs文件中引用NHibernate的类库。添加引用如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using NHibernate;
using NHibernate.Cfg;
namespace HelloNhibernate
{
class Program
{
static void Main(string[] args)
{
}
}
}
现在你的解决方案已经建立,你准备去写你第一个NHibernate程序。
2.1.3 创建Employee类
程序的目的是去存储一条Employee的记录到数据库中,然后检索这条数据显示出来。程序需要一个简单的持久化类Employee,这个类代表了一个被公司聘用的人。
在Visual Studio中,添加一个class文件,命名为Employee.cs。输入一下代码:
namespace HelloNhibernate
{
class Employee
{
public int id;
public string name;
public Employee manager;
public string SayHello()
{
return string.Format(
"'Hello World!', said {0}.", name);
}
}
}
Employee类有三个字段:主键Id,员工的名字(name)和也给指向员工管理员的引用。主键允许程序访问数据库的主键。如果两个员工有相同的主键,就被视为是在数据库中的同一行数据。我们选择了int类型作为主键的类型,但这不是必须的。NHibernate允许为主键配备任何类型。你将会在后面看到。
注意到我们使用了共有的字段而不是属性,这只是为了让代码更加简短,但不是一种好的做法。
Employee的实例是由NHibernate管理的,但这不是必须的。因为Employee对象没有继承任何NHibernate指定的类或者借口,你可以使用它就像其他.NET类那样:
Employee fred = new Employee();
fred.name = "Fred Bloggs";
Console.WriteLine(fred.SayHello());
代码的确如你所想的运行:显示“HelloWorld, said Fred Bloggs”。这是一个很重要的特性。持久化类可以被NHibernate使用或不是由NHibernate使用——没有特殊的要求。当然,我们是在NHibernate是怎么使用持久化类的,因此,首先我们应该建立数据库,然后演示怎样使用NHibernate去保存一条Employee记录到数据库中。
2.1.4 建立数据库
你需要建立一个数据库,以便NHibernate可以存储实体类。建立一个数据库只需要几分钟。NHibernate可以工作在很多不同的数据库上,我们使用SQL Server 2005为例子。
打开Microsoft SQL Server Management Studio,新建一个查询窗口,输入以下SQL语句去创建一个数据库和数据库表:
create database HelloNHibernate
Go
Use HelloNHibernate
GO
create table Employee(
id int identity primary key,
name varchar(50),
manager int
)
GO
运行代码,这样我们就建立了一个我们需要的数据库了。
我们将在第九章向你展示使用NHibernate自动的根据程序建立表。这样你就不用手动的去写SQL!
2.1.5 创建一个Employee对象,保存到数据库中
代码如下。这段代码包含了两个方法:CreateEmployeeAndSaveToDatabase和OpenSession。你可以把这段代码敲进Program.cs文件的Main()方法的下面。
static void CreateEmployeeAndSaveToDatabase()
{
Employee tobin = new Employee();
tobin.name = "Tobin Harris";
using (ISession session = OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
session.Save(tobin);
transaction.Commit();
}
Console.WriteLine("Saved Tobin to the database");
}
}
static ISession OpenSession()
{
if (factory == null)
{
Configuration c = new Configuration();
c.AddAssembly(Assembly.GetCallingAssembly());
factory = c.BuildSessionFactory();
}
return factory.OpenSession();
}
static ISessionFactory factory;
CreateEmployeeAndSaveToDatabase函数调用了NHibernate的Session和Transaction接口。你还不可以运行代码;但我现在告诉你运行会发上什么事情。运行这段代码,NHibernate会执行以下SQL代码:
Insert into Employee (name, manager)
Values (‘Tobin Harris’, null)
主键Id不是在这里初始化的,但是你要从哪里得到Id的值呢?它是数据库生成的数据的唯一标识,它在调用Save()方法时被NHibernate捕获,赋值到Employee实例中。
我们在这里不深入讨论OpenSession方法,但是我会配置NHibernate,来返回一个session,让你可以保存、加载和搜索在你的数据库中。不要像现在这样直接使用OpenSession到你的实际项目中,你将在后面学到更加简便的方法去应用NHibernate。
现在你已经定义了Employee类和实现了添加一条记录到数据库中了。我们同样需要检索一条记录并更新这条记录到数据库中。
2.1.6 从数据库加载Employee
让我们添加代码去检索所有的Employee从数据库。输入以下代码:
static void LoadEmployeesFromDatabase()
{
using (ISession session = OpenSession())
{
IQuery query = session.CreateQuery("from Employee as emp order by emp.name asc");
IList<Employee> foundEmployees = query.List<Employee>();
Console.WriteLine("\n{0} employees found:", foundEmployees.Count);
foreach (Employee employee in foundEmployees)
Console.WriteLine(employee.SayHello());
}
}
字符串"from Employee as emp order by emp.name asc"是NHibernate的查询表达式,这时一种面向对象的查询语言(HQL)。当query.List()被调用时,这种语言被自动转化为如下SQL语句:
select e.id, e.name, e.manager
from Employee e
order by e.name asc
如果你没有使用过一种ORM工具(如NHibernate),你可能希望看到有SQL说明在代码中。但是你不会看到,因为全部的SQL都是在运行时生成的。
到不前为止,你已经定义了Employee实体类,建立了数据库,用代码写了创建一个Employee对象,然后从数据库中检索这条记录。现在,你将写XML去告诉NHibernate关于Employee实体类和怎样保存Employee到数据库中。
2.1.7 创建mapping文件
为了去配置NHibernate,它首先需要一些关于Employee类的信息,用来持久化。这些信息通常由XML mapping文件提供。这个文件指定了Employee的属性对应到Employees表的哪一列。以下是mapping的代码:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
auto-import="true">
<class name="HelloNhibernate.Employee,HelloNhibernate" lazy="false">
<id name="id" access="field">
<generator class="native" />
</id>
<property name="name" access="field" column="name" />
<many-to-one access="field" name="manager" column="manager" cascade="all"/>
</class>
</hibernate-mapping>
为了去添加mapping文件到你的解决方案中,按以下步骤做:
1、 右击HelloNHibernate项目,选择添加>新建项目。
2、 选择XML文件,命名为Employee.hbm.xml。
3、 点击确定。
4、 在解决方案窗口中选中这个xml文件,在属性窗口中,生成操作属性的值改为嵌入资源。这是非常重要的,因为这样NHibernate才可以找到mapping文件。
5、 现在赋值上面代码到Employee.hbm.xml文件。
Mapping文件告诉了NHibernate,Employee类是表Emploees表的持久化类,字段id对应列id,name字段对应列name,manager属性对应列manager,manager是一对多的关系。(现在不要担心细节的问题。)
正如你看到的,xml文档不是很难去理解。你可以很容易的手写出来。在第三章,我们将讨论怎样生成xml文件嵌入到源代码中区。无论你选择哪一种方式,NHibernate有足够的能力去自动生成SQL语句去完成增、删、改、查。你不再需要编写SQL语句。
我们已经完成了持久类的配置,现在我们去配置NHibernate吧。
2.1.8 配置你的应用程序
如果你使用过DataSets或者DataReaders去连接数据库,你可能对存储连接字符串在你的配置文件中非常熟悉。配置NHibernate类似;你添加信息到config文件中,如下步骤所示:
1、 右击HelloNhibernate项目,选择添加>新建项目。
2、 选择应用程序配置文件。点击确定。
3、 赋值下面的xml到文件中:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="nhibernate"
type="System.Configuration.NameValueSectionHandler,
System, Version=1.0.3300.0,Culture=neutral,
PublicKeyToken=b77a5c561934e089"
/>
</configSections>
<nhibernate>
<add key="hibernate.show_sql"
value="false" />
<add key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider" />
<add key="hibernate.dialect"
value="NHibernate.Dialect.MsSql2000Dialect" />
<add key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver" />
<add key="hibernate.connection.connection_string"
value="Data Source=127.0.0.1;
Database=HelloNHibernate;Integrated Security=SSPI;" />
</nhibernate>
</configuration>
这里有很多xml。但是,NHibernate是非常灵活的,它有多种方式去配置。你可能需要修改hibernate.connection.connection_string的值去连接你电脑上的数据库。
上面的配置是针对NHibernate1.2.1GA的,如果你使用NHibernate2.0或更高的版本,你应该用如下的xml代替:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="hibernate-configuration"
type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="connection.provider">
NHibernate.Connection.DriverConnectionProvider
</property>
<property name="connection.driver_class">
NHibernate.Driver.SqlClientDriver
</property>
<property name="connection.connection_string">
Server=(local);database=HelloNHibernate;Integrated Security=SSPI;
</property>
<property name="dialect">
NHibernate.Dialect.MsSql2000Dialect
</property>
<property name="show_sql">
false
</property>
</session-factory>
</hibernate-configuration>
</configuration>
2.1.9 更新Employee
你已经实现了保存和加载Employees了,在你运行程序之前,让我们看一下NHibernate是怎样更新实体类的。创建一个Employee对象,如下所示。把这段代码疏导Program.cs文件的下面。
static void UpdateTobinAndAssignPierreHenriAManager()
{
using (ISession session = OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
IQuery q = session.CreateQuery("from Employee where name='Tobin Harris'");
Employee tobin = q.List<Employee>()[0];
tobin.name = "Tobin David Harris";
Employee pierreHenri = new Employee();
pierreHenri.name = "Pierre Henri Kuate";
tobin.manager = pierreHenri;
transaction.Commit();
Console.WriteLine("Updated Tobin and added Pierre Henri");
}
}
}
这段代码,NHibernate实际执行以下代码:
select e.id, e.name, e.manager
from Employee e
where e.id = 1
insert into Employee (name, manager)
values ('Pierre Henri Kuate', null)
declare @newId int
select @newId = scope_indetity()
update Employees
set name = 'Tobin David Harris', manager = @newId
where id= 1
注意到NHibernate发现了修改了第一个Employee(Tobin)的name和manager,然后自动地更新到数据库。这是NHibernate的一个特性:automatic dirty checking。这个特性当我们修改了持久化类的时候,明确的告诉NHibernate去更新数据库。类似的,你可以看到Employee(Pierre Henri)也被保存了。这个特性叫:级联保存。当第一个类保存时,与它关联的类也会发生保存。同样注意到SQL的顺序与程序的顺序不一致。这是因为NHibernate使用了一些算法去决定SQL的顺序,而去避免发生外键冲突。这个特性叫tracsactional write-behind。
2.1.10 运行程序
在运行程序之前,你需要把下面的代码敲到Main()函数中:
CreateEmployeeAndSaveToDatabase();
UpdateTobinAndAssignPierreHenriAManager();
LoadEmployeesFromDatabase();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
运行程序,它会输出:
Saved Tobin to the database
Updated Tobin and added Pierre Henri
2 employees found:
'Hello World!', said Pierre Henri Kuate.
'Hello World!', said Tobin David Harris.
Press any key to exit...