Table of Contents – NHibernate in Action

Table of Contents

Copyright

Brief Table of Contents

Table of Contents

List of Figures

List of Tables

List of Listings

Foreword

Preface

Acknowledgments

About This Book

1. Discovering ORM with NHibernate

Chapter 1. Object/relational persistence in .NET

1.1. What is persistence?

1.1.1. Relational databases

1.1.2. Understanding SQL

1.1.3. Using SQL in .NET applications

1.1.4. Persistence in object-oriented applications

1.1.5. Persistence and the layered architecture

1.2. Approaches to persistence in .NET

1.2.1. Choice of persistence layer

1.2.2. Implementing the entities

1.2.3. Displaying entities in the user interface

1.2.4. Implementing CRUD operations

1.3. Why do we need NHibernate?

1.3.1. The paradigm mismatch

1.3.2. Units of work and conversations

1.3.3. Complex queries and the ADO.NET Entity Framework

1.4. Object/relational mapping

1.4.1. What is ORM?

1.4.2. Why ORM?

1.5. Summary

Chapter 2. Hello NHibernate!

2.1. “Hello World” with NHibernate

2.1.1. Installing NHibernate

2.1.2. Create a new Visual Studio project

2.1.3. Creating the Employee class

2.1.4. Setting up the database

2.1.5. Creating an Employee and saving to the database

2.1.6. Loading an Employee from the database

2.1.7. Creating a mapping file

2.1.8. Configuring your application

2.1.9. Updating an Employee

2.1.10. Running the program

2.2. Understanding the architecture

2.2.1. The core interfaces

2.2.2. Callback interfaces

2.2.3. Types

2.2.4. Extension interfaces

2.3. Basic configuration

2.3.1. Creating a SessionFactory

2.3.2. Configuring the ADO.NET database access

2.4. Advanced configuration settings

2.4.1. Using the application configuration file

2.4.2. Logging

2.5. Summary

2. NHibernate deep dive

Chapter 3. Writing and mapping classes

3.1. The CaveatEmptor application

3.1.1. Analyzing the business domain

3.1.2. The CaveatEmptor domain model

3.2. Implementing the domain model

3.2.1. Addressing leakage of concerns

3.2.2. Transparent and automated persistence

3.2.3. Writing POCOs

3.2.4. Implementing POCO associations

3.2.5. Adding logic to properties

3.3. Defining the mapping metadata

3.3.1. Mapping using XML

3.3.2. Attribute-oriented programming

3.4. Basic property and class mappings

3.4.1. Property mapping overview

3.4.2. Using derived properties

3.4.3. Property access strategies

3.4.4. Taking advantage of the reflection optimizer

3.4.5. Controlling insertion and updates

3.4.6. Using quoted SQL identifiers

3.4.7. Naming conventions

3.4.8. SQL schemas

3.4.9. Declaring class names

3.4.10. Manipulating metadata at runtime

3.5. Understanding object identity

3.5.1. Identity versus equality

3.5.2. Database identity with NHibernate

3.5.3. Choosing primary keys

3.6. Fine-grained object models

3.6.1. Entity and value types

3.6.2. Using components

3.7. Introducing associations

3.7.1. Unidirectional associations

3.7.2. Multiplicity

3.7.3. The simplest possible association

3.7.4. Making the association bidirectional

3.7.5. A parent/child relationship

3.8. Mapping class inheritance

3.8.1. Table per concrete class

3.8.2. Table per class hierarchy

3.8.3. Table per subclass

3.8.4. Choosing a strategy

3.9. Summary

Chapter 4. Working with persistent objects

4.1. The persistence lifecycle

4.1.1. Transient objects

4.1.2. Persistent objects

4.1.3. Detached objects

4.1.4. The scope of object identity

4.1.5. Outside the identity scope

4.1.6. Implementing Equals() and GetHashCode()

4.2. The persistence manager

4.2.1. Making an object persistent

4.2.2. Updating the persistent state of a detached instance

4.2.3. Retrieving a persistent object

4.2.4. Updating a persistent object transparently

4.2.5. Making an object transient

4.3. Using transitive persistence in NHibernate

4.3.1. Persistence by reachability

4.3.2. Cascading persistence with NHibernate

4.3.3. Managing auction categories

4.3.4. Distinguishing between transient and detached instances

4.4. Retrieving objects

4.4.1. Retrieving objects by identifier

4.4.2. Introducing Hibernate Query Language

4.4.3. Query by Criteria

4.4.4. Query by Example

4.4.5. Fetching strategies

4.4.6. Selecting a fetching strategy in mappings

4.4.7. Tuning object retrieval

4.5. Summary

Chapter 5. Transactions, concurrency, and caching

5.1. Understanding database transactions

5.1.1. ADO.NET and Enterprise Services/COM+ transactions

5.1.2. The NHibernate ITransaction API

5.1.3. Flushing the session

5.1.4. Understanding connection-release modes

5.1.5. Understanding isolation levels

5.1.6. Choosing an isolation level

5.1.7. Setting an isolation level

5.1.8. Using pessimistic locking

5.2. Working with conversations

5.2.1. An example scenario

5.2.2. Using managed versioning

5.2.3. Optimistic and pessimistic locking compared

5.2.4. Granularity of a session

5.2.5. Other ways to implement optimistic locking

5.3. Caching theory and practice

5.3.1. Caching strategies and scopes

5.3.2. The NHibernate cache architecture

5.3.3. Caching in practice

5.4. Summary

Chapter 6. Advanced mapping concepts

6.1. Understanding the NHibernate type system

6.1.1. Associations and value types

6.1.2. Bridging from objects to database

6.1.3. Mapping types

6.1.4. Built-in mapping types

6.1.5. Using mapping types

6.2. Mapping collections of value types

6.2.1. Storing value types in sets, bags, lists, and maps

6.2.2. Collections of components

6.3. Mapping entity associations

6.3.1. One-to-one associations

6.3.2. Many-to-many associations

6.4. Mapping polymorphic associations

6.4.1. Polymorphic many-to-one associations

6.4.2. Polymorphic collections

6.4.3. Polymorphic associations and table-per-concrete-class

6.5. Summary

Chapter 7. Retrieving objects efficiently

7.1. Executing queries

7.1.1. The query interfaces

7.1.2. Binding parameters

7.1.3. Using named queries

7.1.4. Using query substitutions

7.2. Basic queries for objects

7.2.1. The simplest query

7.2.2. Using aliases

7.2.3. Polymorphic queries

7.2.4. Restriction

7.2.5. Comparison operators

7.2.6. String matching

7.2.7. Logical operators

7.2.8. Ordering query results

7.3. Joining associations

7.3.1. NHibernate join options

7.3.2. Fetching associations

7.3.3. Using aliases with joins

7.3.4. Using implicit joins

7.3.5. Theta-style joins

7.3.6. Comparing identifiers

7.4. Writing report queries

7.4.1. Projection

7.4.2. Using aggregation

7.4.3. Grouping

7.4.4. Restricting groups with having

7.4.5. Improving performance with report queries

7.4.6. Obtaining DataSets

7.5. Advanced query techniques

7.5.1. Dynamic queries

7.5.2. Collection filters

7.5.3. Subqueries

7.6. Native SQL

7.6.1. Using the ISQLQuery API

7.6.2. Named SQL queries

7.6.3. Customizing create, retrieve, update, and delete commands

7.7. Optimizing object retrieval

7.7.1. Solving the n+1 selects problem

7.7.2. Using Enumerable() queries

7.7.3. Caching queries

7.7.4. Using profilers and NHibernate Query Analyzer

7.8. Summary

3. NHibernate in the real world

Chapter 8. Developing NHibernate applications

8.1. Inside the layers of an NHibernate application

8.1.1. Using patterns and methodologies

8.1.2. Building and testing the layers

8.1.3. The domain model

8.1.4. The business layer

8.1.5. The persistence layer

8.1.6. The presentation layer

8.2. Solving issues related to .NET features

8.2.1. Working with web applications

8.2.2. .NET remoting

8.3. Achieving goals and solving problems

8.3.1. Design goals applied to an NHibernate application

8.3.2. Identifying and solving problems

8.3.3. Use the right tool for the right job

8.4. Integrating services: the case of audit logging

8.4.1. Doing it the hard way

8.4.2. Doing it the NHibernate way

8.4.3. Other ways of integrating services

8.5. Summary

Chapter 9. Writing real-world domain models

9.1. Development processes and tools

9.1.1. Top down: generating the mapping and the database from entities

9.1.2. Middle out: generating entities from the mapping

9.1.3. Bottom up: generating the mapping and the entities from the database

9.1.4. Automatic database schema maintenance

9.2. Legacy schemas

9.2.1. Mapping a table with a natural key

9.2.2. Mapping a table with a composite key

9.2.3. Using a custom type to map legacy columns

9.2.4. Working with triggers

9.3. Understanding persistence ignorance

9.3.1. Abstracting persistence-related code

9.3.2. Applying the Observer pattern to an entity

9.4. Implementing the business logic

9.4.1. Business logic in the business layer

9.4.2. Business logic in the domain model

9.4.3. Rules that aren’t business rules

9.5. Data-binding entities

9.5.1. Implementing manual data binding

9.5.2. Using data-bound controls

9.5.3. Data binding using NHibernate

9.5.4. Data binding using ObjectViews

9.6. Filling a DataSet with entities’ data

9.6.1. Converting an entity to a DataSet

9.6.2. Using NHibernate to assist with conversion

9.7. Summary

Chapter 10. Architectural patterns for persistence

10.1. Designing the persistence layer

10.1.1. Implementing a simple persistence layer

10.1.2. Implementing a generic persistence layer

10.2. Implementing conversations

10.2.1. Approving a new auction

10.2.2. Loading objects on each request

10.2.3. Using detached persistent objects

10.2.4. Using the session-per-conversation pattern

10.2.5. Choosing an approach to conversations

10.3. Using NHibernate in an Enterprise Services application

10.3.1. Rethinking DTOs

10.3.2. Enabling distributed transactions for NHibernateHelper

10.4. Summary

Appendix A. SQL fundamentals

Tables

Relational model

DDL and DML

Table operations

Queries

Appendix B. Going forward

What you need

Practice makes perfect

Problem solving

Staying up to date

Index