Category Archives: NHibernate

The Repository Pattern: Links, News and Resources (1)

These are my links about Repository Pattern: the differences with DAOs (Data Access Objects); examples with NHibernate, Entity Framework; its use in DDD; its relation to IUnitOfWork; discussion about how to query a repository; the influence of Linq/IQueriable in the evolution of this pattern in .NET (LINQ/IQueryable is a missing piece in Java). There are interesting discussions in Spanish, too. I recommend you should translate them.

Repository
http://martinfowler.com/eaaCatalog/repository.html

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.

LLBLGenPro, Entity Framework 4.1, and the Repository Pattern
http://www.mattjcowan.com/funcoding/2011/09/25/llblgen-ef-repository-pattern/

HunabKu: LINQ and Repository
http://fabiomaulo.blogspot.com/2009/06/linq-and-repository.html

Revisiting the Repository and Unit of Work Patterns with Entity Framework
http://blogs.microsoft.co.il/blogs/gilf/archive/2010/06/21/revisiting-the-repository-and-unit-of-work-patterns-with-entity-framework.aspx

EFMVC
http://efmvc.codeplex.com/
Demo web app using ASP.NET MVC 3 RTM, Razor, EF Code First and Unity 2.0
Repository Pattern and Unit of Work

Repository is Dead: Long Live Repository
http://codebetter.com/gregyoung/2009/04/23/repository-is-dead-long-live-repository/

Repository is the new Singleton
http://ayende.com/blog/3955/repository-is-the-new-singleton

DDD: The Generic Repository
http://codebetter.com/gregyoung/2009/01/16/ddd-the-generic-repository/

The Repository Pattern
http://blogs.hibernatingrhinos.com/nhibernate/archive/0001/01/01/the-repository-pattern.aspx

N-Tiers using POCOs and Entity Framework – Part Two: Model and Entities
http://blog.jorgef.net/2010/09/n-tiers-pocos-ef-2.html

N-Tiers using POCOs and Entity Framework – Part Five: DataAccess Layer
http://blog.jorgef.net/2010/09/n-tiers-pocos-ef-5.html

N-Tiers using POCOs and Entity Framework – Part Six: Source Code
http://blog.jorgef.net/2011/02/n-tiers-pocos-ef-6.html

Using the NHibernate Repository Pattern in C# ASP .NET
http://jasper-net.blogspot.com/2011/04/using-nhibernate-repository-pattern-in.html

Mock a database repository using Moq
http://www.codeproject.com/Articles/47603/Mock-a-database-repository-using-Moq.aspx

The wages of sin: Proper and improper usage of abstracting an OR/M
http://ayende.com/blog/4788/the-wages-of-sin-proper-and-improper-usage-of-abstracting-an-or-m

The wages of sin: Over architecture in the real world
http://ayende.com/blog/4786/the-wages-of-sin-over-architecture-in-the-real-world

Architecting in the pit of doom: The evils of the repository abstraction layer
http://ayende.com/blog/4784/architecting-in-the-pit-of-doom-the-evils-of-the-repository-abstraction-layer
Better Domain-Driven Design Implementation
http://www.udidahan.com/2007/03/06/better-domain-driven-design-implementation/

Entities, Services and what goes between them…
http://ayende.com/blog/2145/entities-services-and-what-goes-between-them

Suteki Shop
http://mikehadlow.blogspot.com/search/label/Suteki%20Shop
http://code.google.com/p/sutekishop/
Suteki Shop is an eCommerce application. The orginal aim is to write a site for a fashion retail business. It includes a product catalogue, shopping cart and order processing.
Using
    * .NET 4.0
    * ASP.NET MVC 3
    * MVC Contrib
    * NHibernate
    * Windsor IoC Container

Hunabku
https://bitbucket.org/fabiomaulo/hunabku
Source for @fabiomaulo blog examples
http://www.fabiomaulo.blogspot.com/

Repository, IQueryable y otras hierbas
http://cprieto.com/index.php/2010/05/20/repository-iqueryablet-y-otras-hierbas/
"cuando Fowler y Eric Evans en su libro DDD definieron Repository no existía el concepto de IQueryable y creo que no muchos se lo veían venir, así que simplemente si asociamos que Repository es una abstración superior del acceso a datos y este se debe comportar como una colección en memoria (mezclando las definiciones de Fowler y Evans) y coincidimos en que en la .Net Framework las colecciones pueden extenderse a IQueryable, es fácil razonar que por definición un repositorio finaliza implementando IQueryable<T> (mera jalada mi filosofía y asociación, pero para filósofo preguntémosle mejor a @ajlopez!)" <—Great! @cprieto reads my philosophy posts 😉
Spanish discussion http://groups.google.com/group/altnet-hispano/browse_thread/thread/9c9e84a850dd00bc

HunabKu: Enhanced Query Object
http://fabiomaulo.blogspot.com/2010/07/enhanced-query-object.html

Implementing Repository Pattern With Entity Framework
http://www.codeproject.com/KB/database/ImplRepositoryPatternEF.aspx

Entity Framework as Repository and UnitOfWork?
http://stackoverflow.com/questions/520065/entity-framework-as-repository-and-unitofwork

Repository or DAO?: Repository
http://fabiomaulo.blogspot.com/2009/09/repository-or-dao-repository.html

Repository or DAO?: DAO
http://fabiomaulo.blogspot.com/2009/09/repository-or-dao-dao.html

Repositories for Value Objects?
http://tech.groups.yahoo.com/group/domaindrivendesign/message/17972

How to use dependency injection and the repository pattern with ASP.NET web services?
http://stackoverflow.com/questions/1449870/how-to-use-dependency-injection-and-the-repository-pattern-with-asp-net-web-servi

FubuMVC Contrib
http://code.google.com/p/fubumvc-contrib/
Contrib for FubuMVC a Front Controller-style MVC framework designed primarily for Web applications built on ASP.NET
Many samples with IRepository, NHibernate, IUnitOfWork

MPBlog Implementation. Part 4
http://www.simplyvinay.com/Post/50/MPBlog-Implementation.-Part-4.aspx
NHibernate Repository and Unit Of Work

Linq specifications: from Argentina with Love
http://joseoncode.com/2009/12/24/linq-specifications-from-argentina-with-love/

IRepository interface
http://weblogs.asp.net/alexeyzakharov/archive/2009/11/18/irepository-interface.aspx

nHibernate, Linq and Queries
http://lucisferre.net/2009/05/19/nhibernate-linq-and-queries/

The DAL should go all the way to UI
http://ayende.com/blog/3958/the-dal-should-go-all-the-way-to-ui

Returning IQueryable<T>
http://weblogs.asp.net/fredriknormen/archive/2008/12/01/returning-iqueryable-lt-t-gt.aspx

Generic Repository
http://grepo.codehaus.org/
The Generic Repository (grepo) is an open source (ASLv2) framework for Java which allows you to access (database) repositories in a generic and consistent manner.

The catalogue metaphor and command-query seperation architectures
http://codebetter.com/iancooper/2009/10/08/the-catalogue-metaphor-and-command-query-seperation-architectures/
Query Objects vs Methods on a Repository
http://www.udidahan.com/2007/03/28/query-objects-vs-methods-on-a-repository/

Using Repository and Unit of Work patterns with Entity Framework 4.0
http://blogs.msdn.com/b/adonet/archive/2009/06/16/using-repository-and-unit-of-work-patterns-with-entity-framework-4-0.aspx

AltNet-Argentina: DAO, Repository y clases Query
http://groups.google.com/group/altnet-argentina/browse_thread/thread/a3f5324ab8418277?pli=1

DDD: The Generic Repository
http://codebetter.com/gregyoung/2009/01/16/ddd-the-generic-repository/

My Links
http://www.delicious.com/ajlopez/repository

More links about other patterns are coming.

Keep tuned!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

NHibernate 3 (Part 7) One-To-Many with Inverse

Previous Post
Next Post

The previous example had a problem: it use one INSERT AND one UPDATE for each chapter. In this post, I use an alternative way to mapping a one-to-many list, using the inverse attribute. As usual, the code is at my AjCodeKata Code Project, under trunk/NHibernate/BookChapters. You can download a “frozen” version from NHibernate3BookChaptersInverse.zip.

I modified the previous solution, adding a new Books.Inverse console project, copying the original Books.Console. And I added a new attribute in Book mapping:

<list name="Chapters" cascade="all-delete-orphan" 
  inverse="true">
  <key column="BookId"/>
  <index column="ChapterIndex"/>
  <one-to-many class="Chapter"/>
</list>

The new attribute is inverse=”true”. With this clue, NHibernate knows that the management of the list and its items are under programmer control. What does it mean? I ran the new console program: each chapter is saved with only ONE insert, but the result in the database was:

No BookId, no ChapterIndex were set! The problem is in the code:

cookbook.Chapters.Add(new Chapter() { Title = "Models and Mappings" });
cookbook.Chapters.Add(new Chapter() { Title = "Configuration and Schema" });
cookbook.Chapters.Add(new Chapter() { Title = "Sessions and Transactions" });

When I created a new Chapter, I didn’t set any Book or Chapter Index information. With inverse=”true”, now that is my responsibility. Then, I changed the Chapter class, adding a new property:

// Used in Inverse example
public virtual int ChapterIndex { get; set; }

And I changed the chapter creation code to:

cookbook.Chapters.Add(new Chapter() { Title = "Models and Mappings", Book = cookbook, ChapterIndex = 0 });
cookbook.Chapters.Add(new Chapter() { Title = "Configuration and Schema", Book = cookbook, ChapterIndex = 1 });
cookbook.Chapters.Add(new Chapter() { Title = "Sessions and Transactions", Book = cookbook, ChapterIndex = 2 });

Now, the output of the insert is:

NHibernate: INSERT INTO Books (Title, Author, Id) VALUES (@p0, @p1, @p2);@p0 = 
'NHibernate Cookbook' [Type: String (4000)], @p1 = 'Jason Dentler' 
[Type: String (4000)], @p2 = b643aa0e-1917-4066-96a4-64a09562a58a [Type: Guid (0)]

NHibernate: INSERT INTO Chapters (Title, Notes, BookId, ChapterIndex, Id) VALUES
 (@p0, @p1, @p2, @p3, @p4);@p0 = 'Models and Mappings' [Type: String (4000)], @p1 
 = NULL [Type: String (4000)], @p2 = b643aa0e-1917-4066-96a4-64a09562a58a
 [Type : Guid (0)], @p3 = 0 [Type: Int32 (0)], @p4 = 
 df9114af-7183-4b1b-9826-d12982a898a5 [Type: Guid (0)]
 
NHibernate: INSERT INTO Chapters (Title, Notes, BookId, ChapterIndex, Id) VALUES
 (@p0, @p1, @p2, @p3, @p4);@p0 = 'Configuration and Schema' 
 [Type: String (4000)], @p1 = NULL [Type: String (4000)], @p2 =
 b643aa0e-1917-4066-96a4-64a09562a58a [Type: Guid (0)], @p3 = 1 [Type: Int32 (0)],
 @p4 = 3fc1df36-c7de-4ff8-add2-8f843b627115 [Type: Guid (0)]

NHibernate: INSERT INTO Chapters (Title, Notes, BookId, ChapterIndex, Id) VALUES
 (@p0, @p1, @p2, @p3, @p4);@p0 = 'Sessions and Transactions' 
 [Type: String (4000)], @p1 = NULL [Type: String (4000)], @p2 = 
 b643aa0e-1917-4066-96a4-64a09562a58a  [Type: Guid (0)], @p3 = 2 [Type: Int32 (0)],
 @p4 = 9c8891e4-6419-4469-aa3a-154f2c908985 [Type: Guid (0)]

Chapters are saved as:

All Ok! Note that I have not to add the chapters to the NHibernate session: they are saved as part of the saved book. But after inverse=true, I should set the inverse relation (Chapter to Book) and order properties.

Next steps: explore deletion, update, more complex mapping, logging options, alternative mappings (Fluent NHibernate, ConfORM, new NHibernate 3.2 mapping by code).

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

NHibernate 3 (Part 6) One-To-Many with Many-To-One

Previous post
Next post

The database is the same from the previous example (the same name and scripts):

But now, I want to have a reference, in the domain, from chapter to book:

public class Chapter
{
    public virtual Guid Id { get; set; }
    public virtual string Title { get; set; }
    public virtual string Notes { get; set; }
	
	// New property
    public virtual Book Book { get; set; } 
}

So, I changed the Chapter mapping to:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Books"
namespace="Books">
  <class name="Chapter" table="Chapters">
    <id name="Id">
      <generator class="guid" />
    </id>
    <property name="Title" not-null="true" />
    <property name="Notes" />
    <many-to-one name="Book" column="BookId" />
  </class>
</hibernate-mapping>

The new element is many-to-one. The Book mapping has no change:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Books"
namespace="Books">
  <class name="Book" table="Books">
    <id name="Id">
      <generator class="guid" />
    </id>
    <property name="Title" not-null="true" />
    <property name="Author" not-null="true"/>
    <list name="Chapters" cascade="all-delete-orphan">
      <key column="BookId"/>
      <index column="ChapterIndex"/>
      <one-to-many class="Chapter"/>
    </list>
  </class>
</hibernate-mapping>

I added the “show_sql” in the configuration file, NHibernate section:

  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
      <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
      <property name="connection.connection_string">Data Source=.\SQLEXPRESS;Initial Catalog=NHibernate3BooksOneToMany;Integrated Security=True</property>
      <property name="proxyfactory.factory_class">
        NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle
      </property>
     <property name="show_sql">true</property>
      <mapping assembly="Books.Console" />
    </session-factory>
  </hibernate-configuration>

This property is very useful when you are learning about NHibernate: it dumps in console the SQL commands that NHibernate executes during its operation. This is the main console program:

ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
using (ISession session = sessionFactory.OpenSession())
{
    using (ITransaction tx = session.BeginTransaction())
    {
        Book cookbook = new Book()
        {
            Title = "NHibernate Cookbook",
            Author = "Jason Dentler",
            Chapters = new List<Chapter>()
        };
        cookbook.Chapters.Add(new Chapter() { Title = "Models and Mappings" });
        cookbook.Chapters.Add(new Chapter() { Title = "Configuration and Schema" });
        cookbook.Chapters.Add(new Chapter() { Title = "Sessions and Transactions" });
        session.Save(cookbook);
        tx.Commit();
        session.Close();
    }
}
using (ISession session = sessionFactory.OpenSession())
{
    foreach (Book book in session.Query<Book>().Fetch(b => b.Chapters))
        {
            System.Console.WriteLine(string.Format("Book {0}", book.Title));
            int nchapter = 0;
            foreach (Chapter chapter in book.Chapters)
            {
                System.Console.WriteLine(string.Format("Chapter {0}:{1}", ++nchapter, chapter.Title));
                System.Console.WriteLine(string.Format("From Book {0}", chapter.Book.Title));
            }
        }
}
System.Console.ReadKey();

A new method is invoke: .Fetch. I’ll explain it below. Now, run the program, and examine the console output. First:

NHibernate: INSERT INTO Books (Title, Author,
 Id) VALUES (@p0, @p1, @p2);@p0 = 'NHibernate Cookbook' [Type: String (4000)], @p1 = 
'Jason Dentler' [Type: String (4000)], 
@p2 = 20d05308-aea1-49f2-9b4a-7441e73dab4e [Type: Guid (0)]

This is the command that inserts the new book. Then:

NHibernate: INSERT INTO Chapters (Title, Notes, BookId, Id) VALUES (@p0, @p1, @p 
2, @p3);@p0 = 'Models and Mappings' [Type: String (4000)], @p1 = NULL [Type: 
String (4000)], @p2 = NULL [Type: Guid (0)], @p3 = 
15ce4169-08ef-4f75-8493-8fe68da7e918 [Type: Guid (0)] 
NHibernate: INSERT INTO Chapters (Title, Notes, BookId, Id) VALUES (@p0, @p1, @p2, @p3);
@p0 = 'Configuration and Schema' [Type: String (4000)], @p1 = NULL [Type: String (4000)],
 @p2 = NULL [Type: Guid (0)], @p3 = 3edb510d-4cbd-44fd-b4a1-094a258ec07f [Type: Guid (0)] 
NHibernate: INSERT INTO Chapters (Title, Notes, BookId, Id) VALUES (@p0, @p1, @p2,
 @p3);@p0 = 'Sessions and Transactions' [Type: String (4000)], @p1 = NULL [Type: String (4000)], @p2 = NULL [Type: Guid (0)], @p3 = af025d1b-cdc6-4c8f-9014-71c5dee135e1 [Type: Guid (0)]

These commands insert the three chapters. Hey! They ARE NOT setting the BookId (note @p2 = NULL) and no mention of ChapterIndex. Curiously, NHibernate set those columns IN A SECOND PASS:

NHibernate: UPDATE Chapters SET BookId = @p0, ChapterIndex = @p1 WHERE Id = @p2; 
@p0 = 20d05308-aea1-49f2-9b4a-7441e73dab4e [Type: Guid (0)], @p1 = 0 [Type: 
Int32 (0)], @p2 = 15ce4169-08ef-4f75-8493-8fe68da7e918 [Type: Guid (0)] 
NHibernate: UPDATE Chapters SET BookId = @p0, ChapterIndex = @p1 WHERE Id = @p2; 
@p0 = 20d05308-aea1-49f2-9b4a-7441e73dab4e [Type: Guid (0)], @p1 = 1 [Type: 
Int32 (0)], @p2 = 3edb510d-4cbd-44fd-b4a1-094a258ec07f [Type: Guid (0)] 
NHibernate: UPDATE Chapters SET BookId = @p0, ChapterIndex = @p1 WHERE Id = @p2; 
@p0 = 20d05308-aea1-49f2-9b4a-7441e73dab4e [Type: Guid (0)], @p1 = 2 [Type: 
Int32 (0)], @p2 = af025d1b-cdc6-4c8f-9014-71c5dee135e1 [Type: Guid (0)]

This is weird (and it’s the reason why we have to define ChapterIndex and BookId as nullable, as I mentioned in the previous example). I would expect NHibernate save in one pass the Book+Chapters. I don’t know why it is the “natural” behavior, and is one of the many behaviors we have to learn in order to master NHibernate. Note that usefulness of show_sql: there are other options to log NHibernate (notable, log4net logging), but this is a simple property you can use now in your initial programs. We should improve this behavior in an upcoming post.

This is the select statement:

NHibernate: select book0_.Id as Id0_0_, chapters1_.Id as Id1_1_, book0_.Title as 
Title0_0_, book0_.Author as Author0_0_, chapters1_.Title as Title1_1_, chapters 
1_.Notes as Notes1_1_, chapters1_.BookId as BookId1_1_, chapters1_.BookId as Boo 
kId0__, chapters1_.Id as Id0__, chapters1_.ChapterIndex as ChapterI5_0__ from Bo 
oks book0_ left outer join Chapters chapters1_ on book0_.Id=chapters1_.BookId

Surprise: The select retrieves Books AND Chapters, using an outer join. In this way, NHibernate can fill the chapters of each book. But this behavior is not the “default” one: the chapters are not loaded every time you retrieves a book. The NHibernate default behavior is to load the Chapters list ONLY when you iterate over it. If you don’t use the list, the chapters are not loaded. The above statement (and the adding of the join) is a consequence of using the Fetch:

foreach (Book book in session.Query<Book>().Fetch(b => b.Chapters))

That additional method says: “Hey, NHibernate! Go and get the book, but the chapters too!”. You can experiment, and remove the Fetch method. Then, this is the partial output (another data set):

NHibernate: select book0_.Id as Id0_, book0_.Title as Title0_, book0_.Author as 
Author0_ from Books book0_ 
Book NHibernate Cookbook 
NHibernate: SELECT chapters0_.BookId as BookId1_, chapters0_.Id as Id1_, chapter 
s0_.ChapterIndex as ChapterI5_1_, chapters0_.Id as Id1_0_, chapters0_.Title as Title1_0_,
 chapters0_.Notes as Notes1_0_, chapters0_.BookId as BookId1_0_ FROM Chapters
 chapters0_ WHERE chapters0_.BookId=@p0;@p0 = 
cfb043eb-6ffc-4727-a5ad-05afe867ab57 [Type: Guid (0)] 
Chapter 1:Models and Mappings 
From Book NHibernate Cookbook 
Chapter 2:Configuration and Schema 
From Book NHibernate Cookbook 
Chapter 3:Sessions and Transactions 
From Book NHibernate Cookbook

There is a select for the book, and then, FOR EACH BOOK (trust me 😉 there is a new select for its chapter. Again: another “behavior” to have into account in order to have a program that doesn’t abuse of database commands. Note that the output:

Book NHibernate Cookbook

PRECEDES the select of the chapters. Until the program iterates the chapter list, NO SELECT is performed. Another point: chapter.Book is not null. Thanks to NHibernate, the reference from Chapter to its parent Book is automatically filled.

So, this is the reason for the added .Fetch method. We have to explore alternatives to circumvent the pair INSERT-UPDATE for each chapter, topic for the next post.

As usual, the code is at my AjCodeKata Code Project, under trunk/NHibernate/BookChapters. You can download a “frozen” version from NHibernate3BookChapters.zip.

Next steps: explore inverse=”true”, other logging options, many-to-many, session cache, etc.

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

NHibernate 3 (Part 5) First One-To-Many Mapping

Previous post
Next post

This time, I want to map this data model:

Each book can have zero, one or more chapters. This is the class diagram for my domain:

This is the code for Book.cs:

public class Book
{
    public virtual Guid Id { get; set; }
    public virtual string Title { get; set; }
    public virtual string Author { get; set; }
    public virtual IList<Chapter> Chapters { get; set; }
}

As usual, the properties are virtual (I should write why, in upcoming post). And note, Chapters is a IList<Chapter>. The IList will be loaded by NHibernate. The Chapter.cs class:

public class Chapter
{
    public virtual Guid Id { get; set; }
    public virtual string Title { get; set; }
    public virtual string Notes { get; set; }
}

The book mapping has a new element:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Books"
namespace="Books">
  <class name="Book" table="Books">
    <id name="Id">
      <generator class="guid.comb" />
    </id>
    <property name="Title" not-null="true" />
    <property name="Author" not-null="true"/>
    <list name="Chapters" cascade="all-delete-orphan">
      <key column="BookId"/>
      <index column="ChapterIndex"/>
      <one-to-many class="Chapter"/>
    </list>
  </class>
</hibernate-mapping>

The <list> element points to the Book property Chapters. The elements will be ordered based on the table column ChapterIndex. BookId and ChapterIndex are not properties in Chapter class. They are columns in Chapter table. The Chapter mapping has no reference to Book class:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Books"
namespace="Books">
  <class name="Chapter" table="Chapters">
    <id name="Id">
      <generator class="guid.comb" />
    </id>
    <property name="Title" not-null="true" />
    <property name="Notes" />
  </class>
</hibernate-mapping>

What does the “cascade=all-delete-orphan” attribute mean? You have more info at:

http://www.nhforge.org/doc/nh/en/index.html#collections-onetomany

The programmer can add and remove chapters from/to a book object, and NHibernate will take care of their persistence. If an object is removed from the list via code, NHibernate will delete the removed chapter IF it has not added to OTHER book. It would be an “orphan” chapter.

This is the code to add and retrieve a book with chapters:

ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
using (ISession session = sessionFactory.OpenSession())
{
    using (ITransaction tx = session.BeginTransaction())
    {
        Book cookbook = new Book()
        {
            Title = "NHibernate Cookbook",
            Author = "Jason Dentler",
            Chapters = new List<Chapter>() { 
                new Chapter() { Title = "Models and Mappings" },
                new Chapter() { Title = "Configuration and Schema" },
                new Chapter() { Title = "Sessions and Transactions" }
            }
        };
        session.Save(cookbook);
        foreach (Book book in session.Query<Book>())
        {
            System.Console.WriteLine(string.Format("Book {0}", book.Title));
            int nchapter = 0;
            foreach (Chapter chapter in book.Chapters)
                System.Console.WriteLine(string.Format("Chapter {0}:{1}", ++nchapter, chapter.Title));
        }
        tx.Commit();
        session.Close();
    }
}

I had a problem: initially, I defined ChapterIndex and BookId as not-null in Chapter table. But, notably, NHibernate requires that those fields could accept null values. So, in my first attempts, I got an error when I save a new book. Then, I read the note (from the above link in NHForge documentation):

Very Important Note: If the <key> column of a <one-to-many> association is declared NOT NULL, NHibernate may cause constraint violations when it creates or updates the association. To prevent this problem, you must use a bidirectional association with the many valued end (the set or bag) marked as inverse="true". See the discussion of bidirectional associations later in this chapter.

I changed the columns to nullable, and all worked OK. I’m still puzzle by this requirement: I expected that NHibernate filled the BookId and ChapterIndex DURING the saving of each chapter. But not. It saved the chapter with those fields with null, and THEN, it updated the row.

The code of this post, as usual, is in my AjCodeKatas Google Project, under trunk/NHibernate/BooksOneToMany. You can download a “current frozen” version from NHibernate3BooksOneToMany.zip.

Next steps: explore more one-to-many options, bidirectional mappings, and more.

My sources of information: book: Jason Dentler’s NHibernate 3.0 Cookbook

http://ayende.com/Blog/archive/2006/12/02/nhibernatecascadesthedifferentbetweenallalldeleteorphansandsaveupdate.aspx

http://www.nhforge.org/doc/nh/en/index.html#collections-onetomany

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

NHibernate 3 (Part 4) Table Per Class

Previous post
Next post

In the previous posts (Table per Hierarchy, Table Per Concrete Class), I implemented two mapping strategies for the same model:

Now, I want to map EACH class to a table:

The solution has two projects, one console project, and the other is a class library:

You can download the code from NHibernate3ItemsTablePerClass.zip. You need to add NHibernate libraries (see a previous post for more details). The database can be created running ExecuteAll.cmd at Sql folder. The command accepts a parameter (e.g. ExecuteAll (local)) as the database server. The default value is .\SQLEXPRESS.

The Item mapping:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerClass.Domain"
namespace="ItemsTablePerClass.Domain">
  <class name="Item" table="Items">
    <id name="Id">
      <generator class="guid.comb" />
    </id>
    <property name="Title" not-null="true" />
    <property name="Description" not-null="true" />
  </class>
</hibernate-mapping>

There is a table attribute, and no discriminator value. The new “thing” is at Note mapping:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerClass.Domain"
namespace="ItemsTablePerClass.Domain">
  <joined-subclass name="Note" extends="Item" table="Notes">
    <key column="Id" />
    <property name="Content" />
  </joined-subclass>
</hibernate-mapping>

The new element is joined-subclass. There is a table attribute for this mapping too. And no id element. It was replaces by the key element that joins both tables.

Similar changes at Page mapping:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerClass.Domain"
namespace="ItemsTablePerClass.Domain">
  <joined-subclass name="Page" extends="Item" table="Pages">
    <key column="Id" />
    <property name="Url"/>
  </joined-subclass>
</hibernate-mapping>

Notably, the main code is the same as in the previous examples. And the domain classes are still untouched.

Next steps: start to research one-to-many mappings, other alternatives to mapping (Fluent NHibernate, ConfORM, new NHibernate 3.2 API).

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

NHibernate 3 (Part 3) Table Per Concrete Class

Previous post
Next post

I want to use the same domain from the previous post:

 

but this time, I want two tables: one for Notes, another for Pages:

The solution has two projects: a class library containing the domain, and the console project:

The code is at my AjCodeKatas Google code project, under trunk/NHibernate/ItemsTablePerConcreteClass. The code doesn’t include the NHibernate libraries, so you must add the references to the solution. As in the previous example, I added as reference to console project: NHibernate.dll from the NHibernate folder Required_Bins and NHibernate.ByteCode.Castle from Required_For_LazyLoading\Castle. I added the .xsd files (XML schemas to support intellisense when writing the mapping files) from NHibernate folde Required_Bins.

You can download the source code directly from NHibernate3ItemsTablePerConcreteClass.zip. If you need the NHibernate 3.x libraries, check http://nhforge.org or download my first example NHibernate3SimpleMapping.zip, that includes them. Check my first post to review: libraries to add, schemas, configuration file, and mapping files (don’t forget to add as embedded resources).

Note that the domain classes are the same: they don’t change from the previous example. I changed the mapping files, not the code. This is a proof of domain independence of our mapping strategy.

First, the Item.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerConcreteClass.Domain"
namespace="ItemsTablePerConcreteClass.Domain">
  <class name="Item" abstract="true">
    <id name="Id">
      <generator class="guid.comb" />
    </id>
    <property name="Title" not-null="true" />
    <property name="Description" not-null="true" />
  </class>
</hibernate-mapping>

First, I removed the discriminator column. There is no such column, because there is no Items table. I added the attribute abstract=”true”. If you forget to add it, then NHibernate “thinks” you have a concrete table for this class. You can remove it, if you have concrete Items that are not Notes, Pages. This is not the case I want to implement: the only “real” items are Notes or Pages. Item is an abstraction in my domain.

The Note.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerConcreteClass.Domain"
namespace="ItemsTablePerConcreteClass.Domain">
  <union-subclass name="Note" extends="Item" table="Notes">
    <property name="Content" />
  </union-subclass>
</hibernate-mapping>

I added the attribute table=”Notes”. And the new element is union-subclass, instead of subclass as in previous example. This new element is the way to say: “the table of this class CONTAINS the columns to save the parent class values”. That is: the table columns are the UNION of the parent class and this class values.

Similar changes for Page.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerConcreteClass.Domain"
namespace="ItemsTablePerConcreteClass.Domain">
  <union-subclass name="Page" extends="Item" table="Pages">
    <property name="Url"/>
  </union-subclass>
</hibernate-mapping>

The main code is practical the same from the previous example:

ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
using (ISession session = sessionFactory.OpenSession())
{
    using (ITransaction tx = session.BeginTransaction())
    {
        Page page1 = new Page();
        page1.Title = "Technical Blob";
        page1.Description = "My Personal Technical Blob in English";
        page1.Url = "https://ajlopez.wordpress.com";
        Page page2 = new Page();
        page2.Title = "My Personal Blob";
        page2.Description = "My Personal Blob in Spanish";
        page2.Url = "http://ajlopez.zoomblog.com";
        Note note1 = new Note();
        note1.Title = "To Do";
        note1.Description = "My To Do List";
        note1.Content = "Practice NHibernate";
        session.Save(page1);
        session.Save(page2);
        session.Save(note1);
        var items = session.Query<Item>(); ;
        foreach (Item item in items)
            System.Console.WriteLine(string.Format("Item {0}", item.Title));
        tx.Commit();
        session.Close();
    }
}

except that this time, I began to use Session.Query<T>, a new extension method for NHibernate sessions, that returns a IQueryable<T> implementing Linq. You MUST add:

using NHibernate.Linq;

to have this method. It is an extension method, not a “natural one” for ISession.

My sources of information:

Book: Jason Dentler’s NHibernate 3.0 Cookbook

http://www.nhforge.org/doc/nh/en/index.html#mapping-declaration-unionsubclass

http://www.nhforge.org/doc/nh/en/index.html#inheritance

Next steps: implement Table per Class strategy, explore one-to-many, lazy collections, etc.Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

NHibernate 3 (Part 2) Table per Hierarchy

Previous post
Next post

In the previous post of this series, I implemented a simple mapping: one class, one table.

But now, I have three classes, with inheritance:

The Id is a System.Guid. I want to have an item collection. Each item can be a Note, with text content, or a web Page, with an associated URL. The solution has two projects:

I keep the source code at my AjCodeKatas Google code project, under trunk/NHibernate/ItemsTablePerHierarchyMapping. The code doesn’t include the NHibernate libraries, so you must add the references to the solution. I added as reference to console project: NHibernate.dll from the NHibernate folder Required_Bins and NHibernate.ByteCode.Castle from Required_For_LazyLoading\Castle.

If you are lazy, like me, and you want a ready-to-build solution, you can download the previous example with NHibernate required files from my Skydrive: NHibernate3SimpleMapping.zip. The code of this post is at: NHibernate3ItemsTablePerHierarchy.zip.

The Domain project has no reference to NHibernate. All the mappings are in the Console project, as embedded resource (don’t forget this).

I have 3 classes to map. But I want to store all data in only one table:

You can generate the database executing ExecuteAll.cmd in Sql directory.

The table Items has a column ItemType, that mark an item as a Note or as a Page. The Item.hbm.xml reference that column as a discriminator:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerHierarchyMapping.Domain"
namespace="ItemsTablePerHierarchyMapping.Domain">
  <class name="Item" table="Items">
    <id name="Id">
      <generator class="guid.comb" />
    </id>
    <discriminator column="ItemType" />
    <property name="Title" not-null="true" />
    <property name="Description" not-null="true" />
  </class>
</hibernate-mapping>

Note that I have no such property in the classes: the discriminator is only used by NHibernate.

Now, I need to map Note objects. How to write the mapping? This is Note.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerHierarchyMapping.Domain"
namespace="ItemsTablePerHierarchyMapping.Domain">
  <subclass name="Note" extends="Item" discriminator-value="Note">
    <property name="Content" />
  </subclass>
</hibernate-mapping>

The new XML element is subclass. It has an extends attribute that reference to the parent class. The discriminator-value attribute has the value to put in the discriminator column when the Item is a Note. If you don’t specify the discriminator value, the name of the class would be used, in this case ItemsTablePerHierarchyMappin.Domain.Note.

The Page.hbm.xml is similar:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="ItemsTablePerHierarchyMapping.Domain"
namespace="ItemsTablePerHierarchyMapping.Domain">
  <subclass name="Page" extends="Item" discriminator-value="Page">
    <property name="Url"/>
  </subclass>
</hibernate-mapping>

You can run the console code:

ISessionFactory sessionFactory = new Configuration().Configure().BuildSessionFactory();
using (ISession session = sessionFactory.OpenSession())
{
    using (ITransaction tx = session.BeginTransaction())
    {
        Page page1 = new Page();
        page1.Title = "Technical Blob";
        page1.Description = "My Personal Technical Blob in English";
        page1.Url = "https://ajlopez.wordpress.com";
        Page page2 = new Page();
        page2.Title = "My Personal Blob";
        page2.Description = "My Personal Blob in Spanish";
        page2.Url = "http://ajlopez.zoomblog.com";
        Note note1 = new Note();
        note1.Title = "To Do";
        note1.Description = "My To Do List";
        note1.Content = "Practice NHibernate";
        session.Save(page1);
        session.Save(page2);
        session.Save(note1);
        IQuery query = session.CreateQuery("from Item");
        foreach (Item item in query.List<Item>())
			System.Console.WriteLine(string.Format("Item {0}", item.Title));
        tx.Commit();
        session.Close();
    }
}
System.Console.ReadKey();

to insert and list items.

This mapping strategy (the old trick of saving every subclass in a single table, using discriminators 😉 is called Table Per Hierarchy (Fowler names it Single Table Inheritance).

Next steps: implement other mapping strategies: one table per concrete class (in this case, Pages and Notes); one table per class (Items, Pages, Notes).

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez