O/R Mapping Tools For DotNet - NHibernate -UserGuiding -Eng
What is NHibernate
NHibernate is a .NET based object persistence library for relational databases. NHibernate is a port of the excellent Java Hibernate relational persistence tool.
NHibernate handles persisting your .NET objects to and from an underlying relational database. Rather than you having to write SQL to get your objects in and out of the database, NHibernate takes care of this for you. Your code only need be concerned with your objects, NHibernate generates the SQL and makes sure that things end up in the correct tables and columns.
Why this Guide?
Anybody who is at all familiar with Hibernate will recognize this as being really similar to Glen Smith's A Hitchhiker's Guide to Hibernate. The content is based on that guide so all of the credit needs to be given to him.
NHibernate's documentation is not anywhere near the point that Hibernate's documentation is. However, the project's are similar enough that the reader should be able to look at Hibernate's documentation and get a very good feel for how NHibernate works.
This doc is intended to get you up and running with NHibernate as quickly as possible. It will cover how to persist a simple object to a table. For more complex examples please see the NUnit test that come with the code.
The Development Process
NHibernate is going to have some tools to help you generate a schema (in codebase now), generate classes from mapping files (on the drawing board), and to update a schema (suggestion from a new developer). However, for this example we are going to assume everything from setting up the table to coding the .NET class is done manually. Here are the steps we are going to perform:
- Create the table to persist the .NET Class to.
- Create a .NET Class that needs to be persisted.
- Create a mapping file so NHibernate knows how to persist the .NET Class' Properties
- Create a configuration file for NHibernate to know how to connect to your Database
- Use the NHibernate API
以下是我们将实现的几个步骤:
1.创建数据库表用于永久性的.Net类.
2.创建.Net类来建立于表的永久映射.
3.创建映像文件用于通知Nhibernate如何对应.Net类的属性.
4.为NHibernate创建一个配置文件用于知晓如何连接数据库.
5.使用NHibernate API应用程序.
Step 1: Writing the SQL
The example we're working through is a very simple one. Consider you've developing a basic user management subsystem for your website. We'll use a Users table that looks like this (I am assuming you already have a database setup - in my case I am calling it NHibernate):
go
CREATE TABLE users (
LogonID varchar(20) NOT NULL default '0',
Name varchar(40) default NULL,
Password varchar(20) default NULL,
EmailAddress varchar(40) default NULL,
LastLogon datetime default NULL,
PRIMARY KEY (LogonID)
)
go
I'm using MS Sql Server 2000, but feel free to use any kind of database you've got a .NET Data Provider driver for. We've got a User table with a Logon ID, Full Name, Password, Email and date of last logon. Pretty standard sort of deal. Next step is to write a .NET Class to handle a given User
Step 2: Creating the .NET Class
When we get a bunch of Users in memory, we'll need some sort of object to hold them for us. NHibernate works via reflection on Properties of the objects, so we'll need to add Properties to the Class we want to persist. A simple Class that can be persisted with NHibernate looks like :
namespace NHibernate.Demo.QuickStart
{
public class User
{
private string id;
private string userName;
private string password;
private string emailAddress;
private DateTime lastLogon;
public User()
{
}
public string Id
{
get { return id; }
set { id = value; }
}
public string UserName
{
get { return userName; }
set { userName = value; }
}
public string Password
{
get { return password; }
set { password = value; }
}
public string EmailAddress
{
get { return emailAddress; }
set { emailAddress = value; }
}
public DateTime LastLogon
{
get { return lastLogon; }
set { lastLogon = value; }
}
}
}
In our example above, we've made the Properties and the Constructor public - but that's not a requirement for NHibernate - it can use public, protected, internal, or even private Properties to persist your data.
Step 3: Writing the Mapping File
So we've now got our SQL table, and the .NET Class that's going to map to it. We still need a way to tell NHibernate how to map from one to the other. This is accomplished via a mapping file. The cleanest (most maintainable) way is to write one mapping file per Class, and if you name it YourObject.hbm.xml
and put it in the same directory as your Class, NHibernate will make things even easier for you. Here's an example of what User.hbm.xml
might look like:
XML镜像文件:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="NHibernate.Demo.QuickStart.User, NHibernate.Demo.QuickStart" table="users">
<id name="Id" column="LogonId" type="String(20)">
<generator class="assigned" />
</id>
<property name="UserName" column="Name" type="String(40)"/>
<property name="Password" type="String(20)"/>
<property name="EmailAddress" type="String(40)"/>
<property name="LastLogon" type="DateTime"/>
</class>
</hibernate-mapping>
Let's have a look at some lines of interest in our file. The first tag of interest is the class
tag. Here we map from the Type name (Class name and Assembly) to the users table in our database. This is slightly different than Hibernate. You have to tell NHibernate where to load the Class from. In this case we are loading the Class NHibernate.Demo.QuickStart.User
in the Assembly NHibernate.Demo.QuickStart
. NHibernate follows the same rules of loading a Type as the .NET Framework - so if you have any confusion about how to specify the Type see the .NET Framework SDK.
Let's skip the id
tag for a moment and talk about the property
tags. A cursory scan will show this is where the work is being done. The name
attribute is the Property on our .NET Class, and the column
is the name of the field in our database. The type
attribute is optional (NHibernate will use reflection for a best-guess if you leave it out) - but highly recommended. Users of Hibernate will notice an immediate difference. In the type a length for the String is being specified. This is needed in NHibernate because ADO.NET requires length and precision/scale IDbParameters to have those properties set before the IDbCommand can be prepared.
Ok. Let's return to that id
tag. You may have guessed that this tag has something to do with mapping to the primary key of the table. You'd be right. The form of the ID tag is very similar to the property tags we just looked at. We map from the Property (name
) to the target database field (column
).
The embedded generator tag tells NHibernate how it should produce the primary key (it's quite happy to generate one for you, of whatever type you prefer, but you'll need to tell it how). In our case, we set it to assigned, meaning that our object is going to generate its own keys (the User object will always need to have a UserID after all). If you're keen to let NHibernate generate keys for you, you'll be interested in class settings like uuid.hex
and uuid.string
(check out the docs for more info).
TIP: If you are using Visual Studio .NET to compile make sure that you set the Build Action
of the User.hbm.xml file to Embedded Resource
. The mapping file will now be a part of the Asssembly. The subtle detail's importance will be evident later.
Step 4: Creating a Configuration File for Your Database
We still haven't told NHibernate where to find our database. The most straightforward way is to feed NHibernate a configuration section from your application's config file. Here's what one might look like:
我们还没有告诉NHibernate如何发现数据库.最常用的一种方式是在我们的应用程序配置文件中为NHibernate创建一个配置段落:
<configuration>
<configSections>
<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.3300.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<nhibernate>
<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="Server=localhost;initial catalog=nhibernate;User ID=someuser;Password=somepwd;Min Pool Size=2"
/>
</nhibernate>
</configuration>
The example above uses a SqlClient driver, connects to the nhibernate database on localhost, and uses the supplied username and password. There are a bunch of other properties you can set to "tune" how NHibernate accesses your database of choice. Once again, checkout the doco for detailed info.
上述例子用了一个SqlClient的驱动,与本地的nhibernate数据库连接,使用提供的用户名和密码.你可以设置若干属性用于有选择的通过NHibernate访问数据库.
Please note that the above configuration file does not have any information about configuring log4net. NHibernate uses log4net to log what is happening internally. In a production application I would recommend configuring log4net and setting NHibernate to the appropriate log level for your scenario.
NHibernate使用log4net来记录内部发生的事务.在开发应用程序的时候我推荐配置log4net来为你的场景设置合适的NHibernate日志级别.
Step 5: Start doing Magic with NHibernate
All the hard work has now been done. If all has gone well so far, you'll have the following:
User.cs
- your C# Class to persistUser.hbm.xml
- your NHibernate mapping fileapp.config
- your configuration settings with ADO.NET connection info (you can do this in code if you like)- A SQL
User
table in your database
Making use of NHibernate in your source is pretty straightforward. The nutshell edition goes:
- Create a Configuration object
- Tell the Configuration about the type of objects you want to store
- Create a Session to your database of choice
- Load, Save and Query your objects
Flush()
your Session back to the database
Let's have a look at some source to make it all much clearer.
First, Create a Configuration Object...
The Configuration object has knowledge of all the mappings that are going on between .NET Classes and the backend database.
首先,创佳一个配置对象.
配置对象知道所有在DotNet类和后台数据库间的映射.
cfg.AddAssembly("NHibernate.Demo.QuickStart");
The Configuration object will look through the Assembly for any files ending in .hbm.xml
. There are other ways to add the Mapping files, but this is probably the easiest.
配置对象将编译所有后缀名为.hbm.xml的文件.虽然有其它方法来添加映射文件,但这可能是最容易的方法.
Then, Create a Session Object...
The ISession object represents a connection to your backend database and the ITransaction represents a NHibernate managed Transaction.
接着,创建一个会话对象.
会话对象表示与后台数据库的连接,事务表示NHibernate管理事务.
ISession session = factory.OpenSession();
ITransaction transaction = session.BeginTransaction();
Then Load, Save and Query your Objects!
Now you just use your objects in a .NET-native way. Would you like to store a new User in the database? Try something like this:
然后读取.保存并且查询你的对象吧(CRUD)
现在你可以对对象使用.Net自己的方式.你想存储一个新用户到数据库么.那么来试下这个:
newUser.Id = "joe_cool";
newUser.UserName = "Joseph Cool";
newUser.Password = "abc123";
newUser.EmailAddress = "joe@cool.com";
newUser.LastLogon = DateTime.Now;
// Tell NHibernate that this object should be saved
session.Save(newUser);
// commit all of the changes to the DB and close the ISession
transaction.Commit();
session.Close();
As you can see, the great thing about NHibernate is the low overhead. Go ahead and query your database and verify that you see the new record in the users table. For the most part you just worry about your business objects, and tell NHibernate when you're done.
就如同你看到的那样.对大多数情况而言,你只需要关心业务对象,只需要告诉NHibernate你什么做.
Let's say you want to retrieve an object when you know the user ID (eg. During a login process to your site). Once a session is opened it's a one-liner; pass in the key and you're done:
在你知道用户号,想要获取一个对象的时候(当用户登陆网站).一旦会话打开,就像门用钥匙你就可以进入一样简单.
session = factory.OpenSession();
User joeCool = (User)session.Load(typeof(User), "joe_cool");
The User object you get back is live! Change its properties and it will get persisted to the database on next Flush()
.
你获取得用户对象是动态的!更改他的属性并且更新到数据库就是一瞬间的事情.
joeCool.LastLogon = DateTime.Now;
// flush the changes from the Session to the Database
session.Flush();
All you had to do to get NHibernate to write the changes you made was to ask it to Flush
the Session. Go ahead and query your database through its tools to verify the Property LastLogin
was updated for "joe_cool".
Even better, you can query your table and get back a System.Collections.IList
of live objects. Try something like this:
更加奇妙的是,你可以查询你的表并且返回一个包含动态对象的System.Collections.IList.看下这个:
foreach(User user in userList)
{
System.Diagnostics.Debug.WriteLine(user.Id + " last logged in at " + user.LastLogon);
}
This query will return the whole table. Typically you'll want a lot more control - like list the Users who have logged in after March 14, 2004 10:00 PM, so you'll do something like:
这种查询可以返回整张表.典型情况下你想获得更多的控制权-比如列出自从去年三月14 2004 10:00 PM登陆的用户,那么你可以这么做:
.Add(Expression.Expression.Gt("LastLogon", new DateTime(2004, 03, 14, 20, 0, 0)))
.List();
foreach(User user in recentUsers)
{
System.Diagnostics.Debug.WriteLine(user.Id + " last logged in at " + user.LastLogon);
}
There are a wealth
There are a wealth of querying options in the documentation, but this will give you an idea of the kind of power Hibernate offers you.
这篇文章还有很多查询方法,但这只不过给你认识下Hibernate的一部分功能.
...And Finally Close()
your session. This will free up the ADO.NET connection that NHibernate is using.
最后关闭你的会话.释放被NHibernate使用的ADO.Net连接.
session.Close();
And that is it...
You've created objects, persisted them, and retrieved (via Criteria queries and key lookup). You've gotta be happy with that!
Now that you've got a feel for NHibernate, you'll be well served by having a good look through the extensive documentation that comes with Hibernate 2.0.3 (remember - the docs in NHibernate are still in the early stages). There's a world of cool stuff to explore like handling one-to-many SQL mapping, persisting sorted and nested collections, tuning performance and much more.
Enjoy! And Happy NHibernating!
Mike Doerfler
Once again - all credit should go to Glen Smith and his article that served as the template for this article
本文来自博客园,作者:Slashout,转载请注明原文链接:https://www.cnblogs.com/SlashOut/archive/2005/03/30/128332.html