Ryan Lanciaux

Random programming blog.

RhinoCommons, NHibernate and ASP.NET MVC Part 3 - the Model

We're going to keep moving now that everything is setup (see part one for setup) and configured (see part two for configuration).

First off we are going to create our classes. The original classes and SQL tables are posted below (these may look familiar – they are from my initial NHibernate post)


Initial Product

    public class Product

    {

        private IList<Product> _RelatedProducts;

        private IList<ProductGroup> _ProductGroups;

 

        public Product()

        {

            _RelatedProducts = new List<Product>();

            _ProductGroups = new List<ProductGroup>();

        }

 

        public virtual string ID { get; private set; }

        public virtual string Title { get; set; }

        public virtual string ImagePath { get; set; }

        public virtual string Description { get; set; }

 

        public virtual IList<Product> RelatedProducts

        {

            get { return _RelatedProducts; }

            set { _RelatedProducts = value; }

        }

        public virtual IList<ProductGroup> ProductGroups

        {

            get { return _ProductGroups; }

            set { _ProductGroups = value; }

        }

    }


Initial ProductGroup

    public class ProductGroup

    {

        public virtual string ProductGroupID { get; set; }

        public virtual string Title { get; set; }

        public virtual IList<Product> Products { get; set; }

    }


SQL Tables

CREATE TABLE [dbo].[SimpleProducts](

    [ProductID] [char](32) NOT NULL,

    [Title] [nvarchar](50) NOT NULL,

    [ImagePath] [nvarchar](300) NULL,

    [Description] [nvarchar](500) NULL

)

 

CREATE TABLE [dbo].[RelatedProductsLookup](

    [ProductID] [char](32) NOT NULL,

    [RelatedProductID] [char](32) NOT NULL

)

 

CREATE TABLE [dbo].[ProductsProductGroupsLookup](

    [ProductGroupID] [char](32) NULL,

    [ProductID] [char](32) NULL

)

 

CREATE TABLE [dbo].[ProductGroups](

    [ProductGroupID] [char](32) NOT NULL,

    [Title] [nvarchar](50) NULL


ActiveRecord Classes
In a traditional NHibernate application, we would write usually our mapping files at this time(see my other NHibernate post for more on that). Since we're using the ActiveRecord pattern, however, we can specify all our mappings inline with the classes. It is important to note that this would not be a pure domain because we're placing our mappings inside the model. Warning if you're sensitive to using Attributes this may not be the code for you…

Our classes will now begin with an ActiveRecord attribute over the class; our properties will begin with Property/HasAndBelongsToMany/etc. Please note, for the sake of the example, I'm being extremely verbose with my attributes. If your table/column names match the class/property names, some of the additional info in the attribute is not necessary.

    [ActiveRecord(Table="SimpleProducts")]

    public class Product

    {

        private IList<Product> _RelatedProducts;

        private IList<ProductGroup> _ProductGroups;

 

        public Product()

        {

            _RelatedProducts = new List<Product>();

            _ProductGroups = new List<ProductGroup>();

        }

 

 

        [PrimaryKey(Column="ProductID", Generator=Castle.ActiveRecord.PrimaryKeyType.UuidHex)]

        public virtual string ID { get; private set; }

 

        [Property(NotNull=true, Length=50, Column="Title")]

        public virtual string Title {get; set; }

 

        [Property(Length=300, NotNull=false, Column="ImagePath")]

        public virtual string ImagePath { get; set; }

 

        [Property(NotNull = false, Length = 500, Column="Description")]

        public virtual string Description { get; set; }

 

        [HasAndBelongsToMany(Table="RelatedProductsLookup", ColumnKey="ProductID", ColumnRef="RelatedProductID")]

        public virtual IList<Product> RelatedProducts

        {

            get { return _RelatedProducts; }

            set { _RelatedProducts = value; }

        }

 

        [HasAndBelongsToMany(Table="ProductsProductGroupsLookup", ColumnKey="ProductID", ColumnRef="ProductGroupID")]

        public virtual IList<ProductGroup> ProductGroups

        {

            get { return _ProductGroups; }

            set { _ProductGroups = value; }

        }

    }


    [ActiveRecord(Table="ProductGroups")]

    public class ProductGroup

    {

        [PrimaryKey(Column="ProductGroupID", Generator=Castle.ActiveRecord.PrimaryKeyType.UuidHex)]

        public virtual string ProductGroupID { get; set; }

 

        [Property(NotNull=true, Length=50, Column="Title")]

        public virtual string Title { get; set; }

 

        [HasAndBelongsToMany(Table="ProductsProductGroupsLookup", ColumnKey="ProductGroupID", ColumnRef="ProductID")]

        public virtual IList<Product> Products { get; set; }

    }


Repository Object
Another added benefit of using the Castle Active Record library is that we can use the Repository<T> for all of our object persistence. Instead of creating our own implementation of IRepository, we can write code like this to save / retrieve / update objects.

Selecting an object (our product IDs are HEX UUID's so this is not exactly accurate)

var p = Repository<Product>.Get(23); 


Saving / Updating

Repository<Product>.Save(p);


The repository is pretty nice – we can save all of our objects outside of the domain, which makes for a much cleaner design. Next time, we'll be looking at the extremely simple MVC application powered by this model and NHibernate Query Generator. Continue to Part 4