Chapter1.  Object/relational persistence in .NET        

本章包括:

■ .NET持久化及关系数据库

■ .NET应用程序分层

■ .NET中持久化的解决方案

■ NHibernate是如何解决关系数据库中的持久化的

■ 高级特性

 

在我们开始NHibernate之前,我们有必要了解一下什么是持久化以及用.NET框架实现它的多种方法。这章我将告诉大家我们为什么要用NHibernate这样的工具。

Do I need to read all this background information?    

如果你想马上马上使用NHibernate,请跳到第二章,直接开始一个NHibernate小程序。没有第一章的知识也同样能明白第二章讲的是什么,但是如果你对持久化这个概念还比较陌生,我们建议你阅读本章。读了本章,你会明白NHibernate的优点、如何使用以及单元工作的(unt of work)的重要概念。

What is persistence?                    

You use persistence to allow data to be stored even when the programs that use it aren’t running.

狭义的理解“持久化”仅仅指把域对象永久保存到数据库中;广义的理解:“持久化包括和数据库相关的各种操作(持久化就是将有用的数据以某种技术保存起来,将来可以再次取出来应用,数据库技术,将内存数据一文件的形式保存在永久介质中(磁盘等)都是持久化的例子)。

1.1.1 Relational databases               

A relational database management system (RDBMS) isn’t specific【针对】 to .NET, and a relational database isn’t necessarily specific to any one application. You can have several applications accessing a single database, some written in .NET, some written in Java or Ruby, and so on. 

Relational technology provides a way of sharing data between many different applications. Even different components within a single application can independently access a relational database (a reporting engine and a logging component, for example).

Relational technology is a common denominator【命名者】of many unrelated systems and technology platforms. The relational data model is often the common enterprise-wide representation of business objects: a business needs to store information about various things such as customers, accounts, and products (the business objects), and the relational database is usually the chosen central place where they’re defined and stored.

This makes the relational database an important piece in the IT landscape. RDBMSs have SQL-based application programming interfaces (APIs). So today’s relational database products are called SQL database management systems or, when we’re talking about particular systems, SQL databases.

1.1.2 Understanding SQL

As with any .NET database development, a solid【牢固的,可靠的】 understanding of relational databases and SQL is a prerequisite【首要必备的】 when you’re using NHibernate. You’ll use SQL to tune【调整、优化】 the performance of your NHibernate application. NHibernate automates many repetitive coding tasks, but your knowledge of persistence technology must extend beyond NHibernate if you want take advantage of the full power of modern SQL databases.

Remember that the underlying goal is robust, efficient management of persistent data. If you feel you may need to improve your SQL skills, then pick up a copy of the excellent books SQL Tuning by Dan Tow [Tow 2003] and SQL Cookbook by Anthony Molinaro [Mol 2005]. Joe Celko has also written some excellent books on advanced SQL techniques. For a more theoretical background, consider reading An Introduction to Database Systems [Date 2004].

1.1.3 Using SQL in .NET applications

.NET offers many tools and choices when it comes to making applications work with SQL databases. You might lean on the Visual Studio IDE, taking advantage of its drag-and- drop capabilities: in a series of mouse clicks, you can create database connections, execute queries, and display editable data onscreen. We think this approach is great for simple applications, but the approach doesn’t scale【衡量】 well for larger, more complex applications.

Alternatively, you can use SqlCommand objects and manually write and execute SQL to build DataSets. Doing so can quickly become tedious【冗长乏味的】; you want to work at a slightly higher level of abstraction so you can focus on solving business problems rather than worrying about data access concerns. If you’re interested in learning more about the wide range of tried and tested approaches to data access, then consider reading Martin Fowler’s Patterns of Enterprise Application Architecture [Fowler 2003], which explains many techniques in depth.

Of all the options, the approach we take is to write classes—or business entities—that can be loaded to and saved from the database. Unlike DataSets, these classes aren’t designed to mirror the structure of a relational database (such as rows and columns).

Instead, they’re concerned with solving the business problem at hand. Together, such classes typically represent the object-oriented domain model.

1.1.4 Persistence in object-oriented applications

In an object-oriented application, persistence allows an object to outlive【比活得长】 the process or application that created it. The state of the object may be stored to disk and an object with the same state re-created at some point in the future. 

This application isn’t limited to single objects—entire graphs of interconnected objects may be made persistent and later re-created. Most objects aren’t persistent; a transient【临时的】 object is one that has a limited lifetime that is bounded by the life of the process that instantiated the object. A simple example is a web control object, which exists in memory for only a fraction of a second before it’s rendered to screen and flushed from memory. Almost all .NET applications contain a mix of persistent and transient objects, and it makes good sense to have a subsystem that manages the persistent ones. 

Modern relational databases provide a structured representation of persistent data, enabling sorting, searching, and grouping of data. Database management systems are responsible for managing things like concurrency and data integrity; they’re responsible for sharing data between multiple users and multiple applications. A database management system also provides data-level security. When we discuss persistence in this book, we’re thinking of all these things:

■ Storage, organization, and retrieval【检索】 of structured data

■ Concurrency and data integrity

■ Data sharing

In particular, we’re thinking of these issues in the context of an object-oriented application that uses a domain model. An application with a domain model doesn’t work directly with the tabular【列成表格的】 representation of the business entities (using DataSets); the application has its own, object-oriented model of the business entities. If a database has ITEM and BID tables, the .NET application defines Item and Bid classes rather than uses DataTables for them.

Then, instead of directly working with the rows and columns of a DataTable, the business logic interacts with this object-oriented domain model and its runtime realization as a graph of interconnected objects. The business logic is never executed in the database (as a SQL stored procedure); it’s implemented in .NET. This allows business logic to use sophisticated【复杂的】 object-oriented concepts such as inheritance and polymorphism. For example, you could use well-known design patterns such as Strategy, Mediator, and Composite [GOF 1995], all of which depend on polymorphic【...】 method calls.

Now, a caveat【警告】: Not all .NET applications are designed this way, nor should they be. Simple applications may be much better off without a domain model. SQL and ADO.NET are serviceable for dealing with pure tabular data, and the DataSet makes CRUD【CreatRetrieveUpdateDelete】 operations even easier. Working with a tabular representation of persistent data is straightforward and well understood.

But in the case of applications with nontrivial business logic, the domain model helps to improve code reuse and maintainability significantly. We focus on applications with a domain model in this book, because NHibernate and ORM in general are most relevant to this kind of application.

It will be useful to understand how this domain model fits into the bigger picture of a software system. To explain this, we take a step back and look at the layered architecture.

1.1.5 Persistence and the layered architecture

Many, if not most, systems today are designed with a layered architecture, and NHibernate works well with that design. What is a layered architecture?

A layered architecture splits a system into several groups, where each group contains code addressing a particular problem area. These groups are called layers. For example, a user interface layer (also called the presentation layer) might contain all the application code for building web pages and processing user input. One major benefit of the layering approach is that you can often make changes to one layer without significant disruption to the other layers, thus making systems less fragile and more maintainable.

The practice of layering follows some basic rules:

■ Layers communicate top to bottom. A layer is dependent only on the layer directly below it.

■ Each layer is unaware of any other layers except the layer just below it.

Business applications use a popular, proven【...】, high-level application architecture that comprises【包含】 three layers: the presentation layer, the business layer, and the persistence layer. See figure 1.1.

 

Let’s take a closer look at the layers and elements in the diagram:

■ Presentation layer —The user interface logic is topmost. In a web application, this layer contains the code responsible for drawing pages or screens, collecting user input, and controlling navigation.

■ Business layer —The exact form of this layer varies widely between applications. But it’s generally agreed that the business layer is responsible for implementing any business rules or system requirements that users would understand as part of the problem domain. In some systems, this layer has its own internal representation of the business domain entities. In others, it reuses the model defined by the persistence layer. We revisit this issue in chapter 3.

■ Persistence layer —The persistence layer is a group of classes and components responsible for saving application data to and retrieving it from one or more data stores. This layer defines a mapping between the business domain entities and the database. It may not surprise you to hear that NHibernate would be

used primarily in this layer.

■ Database —The database exists outside the .NET application. It’s the actual, persistent representation of the system state. If a SQL database is used, the database includes the relational schema and possibly stored procedures.

■ Helper/utility classes —Every application has a set of infrastructural helper or utility classes that support the other layers: for example, UI widgets, messaging classes, Exception classes, and logging utilities. These infrastructural elements aren’t considered to be layers, because they don’t obey the rules for interlayer dependency in a layered architecture.

Should all applications have three layers?

Although a three-layers architecture is common and advantageous in many cases, not all .NET applications are designed like that, nor should they be. Simple applications may be better off without complex objects. SQL and the ADO.NET API are serviceable for dealing with pure tabular data, and the ADO.NET DataSet makes basic operations even easier. Working with a tabular representation of persistent data is straightforward and well understood.