Ryan LanciauxNew Media Mercenary

Using NHibernate (years after I should have been)

April 30, 2008 by ryan

As mentioned in my last post, I've been starting to use NHibernate in some of my more recent projects. I checked it out years ago and I completely hated it (maybe becuase I was a newer developer -- not totally sure). More recently, however, I've realized some of the benefits of Domain Driven Design and thought its about time to give Hibernate another shot. I'm admittedly pretty new to Hibernate so any feedback would be appreciated!

Classes 

    public class ProductGroup

    {

        public virtual string ProductGroupID { get; set; }

        public virtual string Title{ get; set;}

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

    } 

    public class SimpleProduct

    {

        private IList<SimpleProduct> _relatedProducts;

 

        public virtual string ID { get; set; }

        public virtual string Title { get; set; }

        public virtual string ImagePath { get; set; }

        public virtual string Description { get; set; }

        public virtual IList<SimpleProduct> RelatedProducts

        {

            get{ return _relatedProducts; }

            private set { _relatedProducts = value;  }

        }

 

        public virtual void AddRelatedProduct(SimpleProduct product)

        {

            if (_relatedProducts == null)

                _relatedProducts = new List<SimpleProduct>();

            _relatedProducts.Add(product);

        }

 

    }

We're going to start out with some very contrived classes (normally would start with tests but this is just for the hibernate concepts)... These classes should be pretty straight forward; they consist only of some basic properties and list methods.

Data Tables 

Next, we need to create our tables to hold the data coming from the Classes -- I've created a product table / product group table and a lookup table for both (there are many-to-many references in both SimpleProduct and ProductGroup). 

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
)    

 You will want to set the Primary Key of the SimpleProduct and Product Groups table to be the ID. 

Hibernate Mappings

Next we're on to the Hibernate mapping files. These files link the columns in the database to the fields/properties in the domain classes. Please check the project documentation for more detailed information on the Hibernate Schemas.

<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"

                  namespace="ProductModel" assembly="ProductModel" default-lazy="false">

  <class name="ProductGroup" table="ProductGroups">

    <id name="ProductGroupID">

      <column name="ProductGroupID" sql-type="char(32)" not-null="true" />

      <generator class="uuid.hex" />

    </id>   

    <property name="Title">

      <column name="Title" length="50" not-null="true" />

    </property>   

    <bag name="Products"  table="ProductsProductGroupsLookup" lazy="false">

      <key column="ProductGroupID" />

      <many-to-many class="SimpleProduct" column="ProductID" />     

    </bag>       

  </class

</hibernate-mapping>

Inside the hibernate mapping tag, we have an element called class where we're defining the relationship between the class and the table in the database. From there we're defining the properties -- Most of this should be pretty straight forward but there are a couple things I would like to focus on. 

    <id name="ProductGroupID">

      <column name="ProductGroupID" sql-type="char(32)" not-null="true" />

      <generator class="uuid.hex" />

    </id>   

 This node is defining the unique ID for the class -- the ID is being created for each item and looks a little something like this: 46abbefc08d14b49a5d15c8a4dd69ff2

    <bag name="Products"  table="ProductsProductGroupsLookup" lazy="false">

      <key column="ProductGroupID" />

      <many-to-many class="SimpleProduct" column="ProductID" />     

    </bag>       

  </class

Here we're defining a many-to-many relationship with Products -- this is bumping up against the lookup table we defined earlier to get all SimpleProducts associated with this class. currently the bag is defining a many-to-many relationship. We're going to assume that a product can exist under any number of product groups -- for instance if we have a video game system it could be under both the Home Entertainment and Electronics product group. See the project documentation for other types of relationships (one-to-many, etc).

SimpleProduct Mapping:

<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"

                  namespace="ProductModel" assembly="ProductModel" default-lazy="false">

  <class name="SimpleProduct" table="SimpleProducts">

    <id name="ID">

      <column name="ProductID" sql-type="char(32)" not-null="true" />

      <generator class="uuid.hex" />

    </id>   

    <property name="Title">

      <column name="Title" length="50" not-null="true" />

    </property>   

    <property name="ImagePath">

      <column name="ImagePath" length="300" not-null="false" />

    </property>   

    <property name="Description">

      <column name="Description" length="500" not-null="false" />

    </property>       

    <bag name="RelatedProducts"  table="RelatedProductsLookup" lazy="false">

      <key column="ProductID" />

      <many-to-many class="SimpleProduct" column="RelatedProductID" />     

    </bag>       

  </class

</hibernate-mapping>
 

 

Accessing The Data

Now that we've defined all of our mappings its time to create some methods to access our data.

    public class ProductGroupRepository

    {

        private ISession _session;

 

        public ProductGroupRepository(ISession session)

        {

            _session = session;

        }

 

        public ProductGroup GetByTitle(string Title)

        {

                return _session.CreateCriteria(typeof(ProductGroup))

                    .Add(Expression.Eq("Title", Title))

                    .UniqueResult<ProductGroup>();

        }

 

        public IList<ProductGroup> List()

        {

                return _session.CreateCriteria(typeof(ProductGroup))

                    .List<ProductGroup>();

 

        }

    }

 

The ISession is the Hibernate object to use when accessing the data -- from what it looks like, these should pretty much line up with a unit of work (More on that here).

In the other methods of the class, we first need to define what type of object we're looking for. In case it's not obvious, we're specifying that in the CreateCriteria section. In the List() method, we're returning a list (of ProductGroups) -- there are no filters or other criteria defined for this operation. In the GetByTitle() method, however,  we're stating that the Title for the product must match the Parameter 'Title'.

Demo Application

I've created a quick demo application using MVC and NHibernate. As I said, I'm still very new to hibernate so there's a lot I'm trying to learn (for instance where the ISession should initially be created and closed in an MVC application). Please let me know of any way that this could be better -- generally I'm writing this to help solidfy my thoughts on the technology, help others (hopefully) and also improve from others feedback. 

If you have tortoise or some other svn client, you can grab the code from http://svn2.assembla.com/svn/NHibernateTest/ -- You will need to change the database connection to whatever your db is. Again I would like to reiterate, it's demo code -- not even close to anything that I would ever use in production but worked out okay for testing. 

kick it on DotNetKicks.com

 

Disclaimer: Use this code at your own risk. 

Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList



NHibernate in an ASP.NET MVC application

April 29, 2008 by ryan

I've recently become interested in using NHibernate for some of my data access. For the past year or so I have been using SubSonic for that, however, I'm trying to take a bit more of a domain driven approach on the project I'm currently messing around on. Although I've only been looking at it for a couple of days, one thing I'm having a little bit of trouble figuring out is where my ISession should be opened / closed in an ASP.NET MVC application. Currently, I'm doing this in the Controller but I'm not totally sure that is the right way to go...

        public ActionResult ViewProduct(string ID)

        {

            using (ISession session = SessionManager.GetCurrentSession())

            {

                SimpleProductRepository repo = new SimpleProductRepository(session);

 

                return RenderView("ViewProduct",

                    new SimpleProductRepository(session).GetByTitle(ID));

            }

        } 


What is the best way to go about this? Also, should I be looking more at using a Unit of Work pattern to achieve this?
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Tags:
Categories: Development
Actions: E-mail | Kick it! | Permalink | commentComments (2) | RSS comment feedComment RSS


Blog Engine.NET Security Patch Available

April 14, 2008 by ryan
If you have not seen one of the other 5 million postings on this, there is now a security patch available for BlogEngine.NET. This weekend an issue was reported where an attacker could obtain the username and password of the site. Thanks BlogEngine.NET team for the quick fix on this!
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Tags: , ,
Categories: General
Actions: E-mail | Kick it! | Permalink | commentComments (0) | RSS comment feedComment RSS


IE8 vs Firefox 3.0b5 : JavaScript Part 1

April 12, 2008 by ryan

Last time I posted on the latest browser from Microsoft vs. Mozilla's latest I had compared page download times between the two browsers. This time, I would like to take a brief look at how they stack up in regard to JavaScript.

John Resig (of jQuery / Mozilla fame) announced the Dromaeo: Javascript Performance Testing suite yesterday. The suite runs some of the same tests as the WebKit team's SunSpider, however, there are some improved methodolgies (see the suite's wiki for more info on this). I don't know how often I feel like doing DNA Sequence Alignment in JavaScript but I think it would be a good way to quickly get some metrics of how both FireFox and IE8 handle the code.

The Comparison:

I ran the tests in groups because there were certain ones that were not finishing under IE8. To be quite honest, I'm not 100% sure if this is an Internet Explorer issue, or an issue with the tests. Both are a work in progress so I would rather not make assumptions at this point. Anyways, the results of the tests are listed below:

Test Name
Firefox 3.0 beta 5 Internet Explorer 8
Fannkuch v122 802.80ms 1032.20ms
Base 64 Encoding and Decoding v122: 2942.00ms Would not finish
DNA Sequence Alignment v116: 420.00ms Would not finish
N-Body Rotation and Gravity v122: 270ms 529.40ms
Prime Number Computation (2) v122: 305.80ms 518.20ms
Recursive Number Calculation v122: 184.40ms 417.80ms
Traversing Binary Trees v122: 156.80ms 422.20ms

The Results

The initial results look like Firefox is performing the more advanced Javascript operations faster than Internet Explorer. That being said, Dromaeo, IE8 and Firefox 3.0b5 are still being developed so a lot could change before the release. For more metrics view a comparison on the Dromaeo site of Safari 3.1, Firefox 3.0b5, Opera 9.5 and IE8b1. Let me know what you think or if you've encountered different results.

kick it on DotNetKicks.com
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList

Tags:
Categories:
Actions: E-mail | Kick it! | Permalink | commentComments (8) | RSS comment feedComment RSS


Gravatar, please bring back PNG files!

April 10, 2008 by ryan
Gravatar recently made some big changes when migrating the site from Ruby on Rails to PHP. While most of these changes are a real benefit, there is one big feature that has been removed -- PNG files are no longer supported! Initially, I was sure it had to be a fluke -- why would someone want to remove PNG files for something like this? However, upon contacting support, my fears were confirmed (email pasted below):

"Gravatar.com has been redesigned to use JPEG images only.  There are certain (still in widespread use) web browsers which do not support PNG files (which would allow for transparent backgrounds.)  I would suggest Adding a background color to your image, and re uploading it."

First off I want to emphasize I really appreciate this service that Gravatar is providing; it has always worked well and come on, it's free! That being said, it is somewhat concerning that the support for PNG files has been dropped for legacy browsers.

While PNG files may not look pretty on IE6, its not an issue that will prevent IE6 (or other legacy browser) users from viewing the site. Moving web standards forward is important! As web developers, I believe its our responsibility to let the end-user know that their overall experience may be better with a newer (standards-compliant) browser. Furthermore, removing the ability to use PNG files for legacy browser support is somewhat harmful! Imagine if iTunes stopped selling MP3s because people on Walkman's couldn't listen to them -- no real technological advancement would be made for fear of alienating some users.

Ultimately, the decision to support PNG files is up to Automattic (the creators of Gravatar). My hope, is that they would allow the Gravatar users to pick the image format of choice while educating their users that PNG files may not show up as expected for some people.


kick it on DotNetKicks.com
What do you think should be done? Should PNG files be supported by Gravatar? Please leave a comment below -- or continue this discussion on your site... this is an important issue for Web Standards.
Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList



Browser Beta Battle : IE8 vs Firefox 3.0b5

April 2, 2008 by ryan

After reading Steve Souders' article on IE8 speed enhancements, I became curious about how page download times in IE8 stacked up against the latest beta of Firefox (3.0b5). I realize that both of these browsers are in beta so the release product may be signficantly different. Also, please keep in mind these results are not very scientific (obviously). To obtain download times, I used Fiddler for Internet Explorer and Firebug for Firefox.

First off, I loaded a several higher volume websites to compare page download times. Each page was loaded three times (for extreme statistical accuracy :P) and the average load time was calculated.

Google News

http://news.google.com

0 Javascript Requests - 0 CSS Requests - 32 Images
Firefox: 1.08 Seconds
IE8: 2.43 Seconds


Amazon

http://www.amazon.com

12 Javascript Requests - 2 CSS Requests - 96 Images
Firefox: 5.59 Seconds
IE8: 4.86 Seconds


Mac.com

http://www.mac.com

15 Javascript Requests - 6 CSS Requests - 44 Images
Firefox: 5.74 Seconds
IE8: 4.52 Seconds


Finally, I ran Steve Souders' Parellel downloads test; the results were almost identical.

Firefox

Internet Explorer


It was really odd to me that Google News loaded almost two times as fast on Firefox while all the other sites loaded close to the same speed or slightly faster on Internet Explorer. The only difference I notice off the bat is the number of JS/CSS files; maybe its something to do with that? It would be very interesting to see how the browsers compare when rendering pages. Have you found results similar to this or know of a good way to test render time? Let me know what you think.

kick it on DotNetKicks.com


Digg It!DZone It!StumbleUponTechnoratiRedditDel.icio.usNewsVineFurlBlinkList







© 2008 Ryan Lanciaux :: powered by BlogEngine.NET