Devlico.Us
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @devlicious

Alan Northam

May 2007 - Posts

  • Getting Started with NHibernate: Part III - Updated

    I've updated the mapping files for Comment and BlogPost in Part III.

    The changes are:

    1. The named query GetCommentsByBlogPostID has been moved into the BlogPost.hbm.xml file, it just makes more sense for it to be there.
    2. <loader query-ref="GetCommentsByBlogPostID"/> was added to the Comments collection mapping in the BlogPost.hbm.xml file, NHibernate will use this query when loading the collection.
    3. cascade="delete", and inverse="true" attributes were added to the Comments collection mapping in the BlogPost.hbm.xml file, the combination of these two setting ensure that when a BlogPost is deleted all of the comments associated with it will also be deleted.  It is unlikely that you would want to delete a BlogPost and all it's comments in a live blog application (although you might want to archive or hide them) but here it serves the purpose of demonstrating these attributes usage.
    4. The Comment mapping file (Comment.hbm.xml) was updated to include a stored procedure call for loading comment entities by ID.

    These changes will be covered in greater detail as the application progresses.  Part IV is coming soon and will include all updates, source code, and SQL Express database.

     

  • Getting Started with NHibernate: Part III

        When mapping objects to the database in NHibernate you can either use XML files or decorate your classes with mapping attributes (NHibernate.Mapping.Attributes).  I've used both but I usually choose XML files simply as a matter of personal preference.  Either method works well and both provide many options for defining the relationship between class and table and configuring it's function.  I'll be using XML files in this tutorial but may work in some mapping attributes later in the process. 

        To get intellisense working with the mapping files you can copy the nhibernate-*.xsd files from the NHibernate source (NHibernate\src\NHibernate\) to C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas (or wherever you installed VS).  There are a few tools that can help by generating the mapping files based on an existing database schema, one that I've had the most success with is MyGeneration (try the template by lujan99).

        As I go through each mapping I'll point out how certain features work but for detailed information on the available options check the official documentation here.  Each of these mapping files will follow the naming convention classname.hbm.xml as this is what NHibernate expects to find when the SessionFactory is initialized (more on this in Part IV).

     

        BlogPost mapping: 

        At the beginning of the file I'm setting the assembly and namespace values.  They aren't required, but if they are not set you will need to fully qualify any class names used including the assembly ( i.e., NHBlog.Domain.BlogPost, NHBlog.Domain).  The class element tells NHibernate what the name of the class is and which table that class maps to, in this case both are named BlogPost.  The id element defines the primary key of the table and which property in the class it maps to.  It's also includes the type (.net data type) and which class is generating these values.  NHibernate includes many different generator classes.  In our example we are using the identity function in SQL Server so the generator is set to native. 

        Each BlogPost will also have a collection of Comments seen here mapped using the bag element.  This mapping is a bit different than normal in that the<loader query-ref="GetCommentsByBlogPostID"/> attribute specifies which query to use to load the collection of comments, in this case a stored procedure.  At the bottom of the file a sql-query is defined to execute the stored procedure GetCommentsByBlogPostID and pass in the value blogPostID.  The load-collection element instructs NHibernate what type of entities to expect as the result of this query.

        Why am I using a stored procedure here?  I don't have to, I could load the collection like any other but doing it this way serves two purposes; to demonstrate the use of stored procedures (a new feature in NHibernate 1.2), and to assist in loading the comments in a threaded conversational manner (see the requirements in Part II).  GetCommentsByBlogPost uses a feature in Sql Server 2005 (and Sql Express 2005) called Common Table Expressions.  More information can be found here.

     

        BlogUser mapping: 

        In BlogUser we have three collections mapped; BlogPosts, Comments, and BlogRoles.  The first two are one-to-many relationships meaning that a single BlogUser can have posted many BlogPosts and made many Comments.  The last is a many-to-many relationship meaning that a BlogUser can belong to many BlogRoles and a BlogRole can contain many BlogUsers.  The table UserRole defines this relationship in the database.  The mapping instructs NHibernate what type of class makes up this collection, which table to use to look up the collection members and which column holds the key for each.

     

        BlogRole mapping: 

         BlogRole has a collection of BlogUsers which represents the other side of the many-to-many relationship defined in BlogUser. 

     

       Comment mapping:

        A Comment has a reference to the BlogUser who made it (MadeBy), the Comment it is replying to (InReplyTo), if any, the BlogPost it is a comment on (BlogPost), and a collection of comments replying to it (Replies).  Also, notice the "Depth" property doesn't allow inserting or updating of this value.  That's because this value/column doesn't actually exist in the database, it's generated when loading a collection of comments.  If you load an individual Comment this value will always be zero.  This mapping is also using a stored procedure but in this case it will be used when loading a comment by id. 

     

        GetCommentsByBlogPostID stored procedure code: 

       

        GetCommentByID stored procedure code: 

       

        In Part IV we will configure NHibernate and begin building the supporting framework needed to use what we have done so far.

  • Getting Started with NHibernate: Part II

        While writing the code necessary for this installment, I found myself falling prey to feature-creep.  So I've decided to keep it fairly simple in the beginning.  However, once the basic components are working I'll start introducing more features.  I thought this might be a good way to demonstrate what is and isn't required to add new functionality to a working NHibernate application.

        The application's initial functionality will consist of blog users being able to post new blog posts, comment on posts,  and reply to other comments.  Only users with the correct role membership will be able to post, all users will be able to comment and reply to comments.  Also, the comments should be threaded so conversations can be followed more easily.

        The domain model has just 4 classes (for now):

     

     NHBlog UML diagram

     

       

        The Sql Express 2005 database will have 5 tables persisting our 4 classes.  The extra database table UserRole will persist the many-to-many relationship between BlogUser and BlogRole. 

     

    NHBlog database diagram

     

        Also notice that the "Depth" property in the Comment class is not actually persisted, it is a read-only value that is generated when a collection of comments for a BlogPost is loaded and represents the level of the comment in the comment hierarchy (threaded convesations!).  See the attachment for the database script.

        In Part III we will create the mapping glue that binds the model and database together.

  • Getting Started with NHibernate: Part I

        When I first started learning and using NHibernate, I read every tutorial, downloaded every example, and studied every code snippet I could get my hands on.  There are some great resources available with one of the best being Billy McCafferty's NHibernate Best Practices.

    In my opinion, the majority of the resources available fall into one of three categories:

    1. Articles that expect and require some familiarity with NHibernate.
    2. Articles or snippets/sample code that are written at such a low level, you're left wondering how the technique demonstrated would be implemented in real world code.
    3. Open source code that dissecting and learning from would be a daunting and tedious task for users new to the concept of NHibernate.

        Each of the resources I refer to provide a lot of useful information.  However, I like to learn by doing and I think a tutorial that provides a step by step guide to implementing NHibernate in a real world application would be beneficial to a lot of prospective NHibernate users.

        In an attempt to fill this void, this is the first article in a series of many.  Each article will cover a bite-sized (byte-sized?) step in the process as we design and implement a blog.  We will finish with an application that is simple enough that we don't get bogged down in unrelated topics but complex enough that in the end we will have a framework that can be used as the foundation for future projects.

        In Part II we will build our domain classes.

More Posts

Our Sponsors

Proudly Partnered With