Gabriel's point of view

Freitag, 22. Juni 2007

Instead of using the ADO.NET data reader as in the reference implementation to fill a CSLA object with data one can as well use an O/R mapper tool like NHibernate and fetch the data through this object layer.

We have the following diagram

where Category, Product and ProductNote are the NHibernate data objects and ProductBO, ProductNotesBO and ProductNoteBO are the CSLA business objects.

Donnerstag, 21. Juni 2007

Some times I want to load an instance of an object which has one or several child collections. Usually I design my object relational mapping to use lazy loading by default. The result of this is that when loading a single instance of a object and accessing its child collections NHibernate spits out at least one additional query per collection. So I have many roudtrips to the server.

Fortuately NHibernate 1.2 offers the new possbility to create a "Multi-Query". The result is (at least for the SQL Server) that only ONE single roundtrip is made to the server and several resultsets are returned.

Let's make an example. We have a Category entity which has two child collections of type Product and Note. That is, any category object can have a list of associated Products and Notes. If I want to display all details of a specific Category on a view, then I have to load the details of the category object and the details of any of the associated products and notes objects. I have at least 3 queries to send to the database.

Now with the following syntax we reduce the roundtrips to the database needed to exactly one:

Freitag, 15. Juni 2007

Often we have the following situation: An entity has some attributes that are important and often accessed and then it has some other attributes that are either rarely used or their content is large in size (e.g. a photo or a document). In such situations it is common to split the entity into two tables. One table containing the important attributes and the other the remaining ones. A typical example is table 'Person' and table 'PersonDetails'. These tables are relatet by a 1 to 0..1 relation. That is a person can have person details but doesn't need to. On the other hand 'person details' always belong to a 'person'.

Question: How can we instruct NHibernate and/or ActiveRecord to give us such a relation. We want to have the possibility to load a list of persons WITHOUT loading also their corresponding details. The details should ONLY be loaded when we really access them. That is called 'Lazy Loading'.

Just using a one-to-one relation doesn't work! We have to use a 'trick' and use a combination of a many-to-one and a one-to-one relation. This solves our problem.

on the "parent" side (Person) we have the many-to-one relation which points to PersonPhoto.

on the "child" side (PersonPhoto) the primary key (PersonID) is the same as on the "parent" side. Thus the value must be "inherited" from the parent. This is the reason to use "foreign" as generator class. The <param> tag just points to the Property from which NHibernate can get this PK value, in our case the property is called Owner (which is the Person who owns this photo).

on the "child" side we have the one-to-one relation which points to Person.

the one-to-one relation sets constrained=true since the person details belongs to a person (a person MUST exists).

ActiveRecord

We can define the same behaviour in ActiveRecord. Here I choose a similar sample as above, a one-to-one relation between a Car and its CarPhoto. Code explains better than many words, thus:

Freitag, 8. Juni 2007

When developing any more or less complex LOB application the developer needs some decent patterns, frameworks and tools to efficiently fullfill the given task. I assemled a list of elements which I personally recommend

Base Framework: .NET 2.0 or 3.0

O/R-Mapping: NHibernate and ActiveRecords

IoC: Castle Windsor Container or MS ObjectBuilder

Testing: NUnit, MbUnit, Rhino.Mocks

Business Layer: CSLA

Smart Client: CAB, SCSF

Tools

VS 2005 Professional or Team Edition

Resharper 2.5 or higher

ActiveWriter Plugin for VS

TestDriven Plugin for VS

Patterns

Presentation Layer

MVC: Model View Controller, or

MVP: Model View Presenter

Processes/Design

Domain Driven Design (DDD)

Test Driven Development (TDD)

Behaviour Driven Development (BDD)

All the items mentioned above need some further discussion and will be covered in more details below and in my future posts.

Acronyms

First let me define the acronyms used so far:

Acronym

Description

O/R-Mapping

Object-Relational Mapping. A technique used to bridge the gap between the relational database and the object oriented application

IoC

Inversion of Control: A technique used to instanciate, instrument and maintain objects during their life time. Especially helpful if one is developing loosely coupled applications

Unit Test

A test methodology used to test the state and behaviour of a single unit (e.g. object)

To bridge the gap between the relational database system (RDBMS) and the object oriented application domain we choose to use NHibernate. NHibernate allows us to define mappings between objects and their corresponding tables in the database via xml mapping files. Not only can one define the mappings between objects and tables but also the relations between different objects can be mapped to the corresponding relations in the database. NHibernate supports 1 to 1, 1 to many and many to many relations. These are the most common scenarios we typically encounter in LOB.When we use a Domain-Driven Design (DDD) NHibernate supports us with the possibility to automatically generate the necessary database schema. Developing the object model first and then derive the database schema from the object model is in our opinion a more "natural" way of implementing a "green field" application than the more "traditional" way of implementing an application where the Entity Relationship Diagram (ERD) is designed first.When using NHibernate one immediately is looking for a way to avoid the tedious task to manually write the xml-mapping files for each object in the domain. Fortunately the Castle Project has ActiveRecord as one of its sub-projects. ActiveRecords allows us to decorate the classes in our domain directly with Attributes instead of writing xml-mapping files. ActiveRecord is well documented and I do not want to repeat this documentation here. But I want to discuss a concrete example.But wait! Do I really have to write my classes by hand and decorate them and its respective properties with Attibutes? Isn't there a "better" way of doing it? Yes, indeed there is: Gökhan Altinören has written a VS PlugIn which allows us to visually desing our object model. Its the ActiveWriter PlugIn which I'll be using in the following example.Example

A person has hobbies. The relation between a person and a hobby is many-to-many since a person can have many hobbies and a single hobby like swimming can be exercised by many different persons.

A person has assigned tasks. The relation between a person and a task is also many-to-many since a person can have many assigned tasks and a single task like "write a blog entry on topic xyz..." can be assigned to many different persons.

A person can blog - as I do here. A person can maintain several blogs but each blog belongs to a single person (at least in my sample). Thus the relation between person and blog is one-to-many.

To a person we want to be able to store a photo. Since a photo can be rather large we decide NOT to store the photo directly in the Person object but create an extra PersonPhoto object which is owned by the Person object. So as a benefit we have the possibility to only load the PersonPhoto data if really needed. The relation between a person and a photo is one-to-one.

A person has an address. But also e.g. a company has an address. So we decide to not make the relation between person and address as one-to-one but rather many-to-one.But the relation has a further restriction in so far that the "many" part of the relation is effectively a unique restriction since a single address cannot (in reality) be shared among different persons (or e.g. companies).

This leads us to the following design (in ActiveWriter)

ClassesFor each class we have to define the mapping via the property window. Just select the corresponding class and modify the atributes similar to the example belowIn the above example the mapping is between the Person class and a table also called Person which is defined in the (database) schema gns.Note that when not defining the Table attribute NHibernate automatically takes the value of the attribute Name as the name for the underlying table.PropertiesNote that each object (or class) has a property Key. This is a value which uniquely identifies an instance of the respective type. The Key property is mapped to the primary key column in the underlying database table.To make our application multi-user friendly I also introduced a Version property for each object. This allows us to handle any concurrent (write) access to a specific object. NHibernate offers built-in functionality for such properties.The other properties are common properties and are all of type string except for the Photo property in the PersonPhoto class which is of type BinaryBlob.Each Property of a class can be configured through the Properties Windows. Just activate the corresponding property in the ActiveWriter designer.For the Version property I have set the following valuesFor the Key Property of the Person object I have set the following values. Note that I use Guid's for the key. One can as well use int or long.In the Column attribute you define how the corresponding column will be called in the underlying table Person. If you don't specify a value then NHibernate will automatically take the value of the attribute Name as the column name. This fact was used for the Version property defined above.The other properties are easy and I'll show here as an example the property Photo of the PersonPhoto classRelationsThe most interesting part are the relations among the different classes (or objects). The first time you use ActiveWriter you might be a little bit confused about the naming convention. The author of ActiveWriter is working on it and will soon provide a detailed description. Never the less let's have a look at the various relation typesOne-to-One relationLet's look at the one-to-one relation between Person and PersonPhoto. I have defined the following attributesWhat does this mean? Source Constrained = True means that a photo cannot exist without a corresponding person but vice versa a person can exist without having a photo (Target Constrained = False).Target Cascade = All means that when saving or deleting a person the owned photo is automatically save or deleted too. On the other hand when I save or delete a photo the corresponding person object is not affected (Source Cascade = None).One-to-Many relationAs an example let's have a look at the relation between Person and Blog(s).In this example consider the "Source..." as the One-side (here the Person) and the "Target..." as the Many-side (here the Blog) of the relation.Note:the Target Lazy = True setting which means that I do not want to have all blogs automatically loaded when I load a person object. Only if I access the person's blog(s) NHibernate shall load the corresponding blog(s). The Property Blogs in the Person class is of type IList. This list is sorted by BlogName (see the Target Order By = BlogName)

.

.

.

.

Many-to-Many relationHere we look at the relation between the Person and Task classes.Any many-to-many relation needs a link table in the database. Here we define the link table to be named PersonTask and residing in the schema gns.The setting Source Lazy = True means that I do not want all tasks to be automatically loaded when I load a person. They should only be loaded when I want to access them.The other settings are more or less self-describing.