Thursday, November 18, 2010

Simple sample for loading parent child records on NHibernate

Object-Relational:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Cfg;
using System.Reflection;
using NHibernate;
using System.Threading;

namespace TestTwoTable
{
    class Program
    {
        static void Main(string[] args)
        {
                                
            if(1 == 1)
            {
                IList<Phone> phones = PhoneList();
    
    
                foreach(Phone p in phones)
                {                                        
                    Console.WriteLine("Phone {0}", p.PhoneNumber);
                    
                    
                    // Try to comment/uncomment Console.WriteLines so you can 
                    // verify that NHibernate indeed lazy loads related parent record,
                    // check your RDBMS log query(s) timestamps to verify that.
                    // 
                    // When using Postgresql on Linux, the log file is in /opt/Postgresql/9.0/data/pg_log
                    // On Mac it is in /Library/PostgreSQL/9.0/data/pg_log
                    // On Windows it is in C:\Program Files (x86)\PostgreSQL\9.0\data\pg_log                                    
                    Console.WriteLine("Owned by {0}", p.Kontact.ContactName);

                    
                    // With lazy loading, the p.Kontact's Phones will not be queried unnecessarily.
                    // The p.Kontact's Phones will only be queried from database when you access it.
                    // Try to comment/uncomment the following code and see that effect in your RDBMS log file.                    .
                    /*
                    foreach(Phone p in p.Kontact.Phones)
                    {
                        Console.WriteLine("Contact's phone {0}", p.PhoneNumber);
                    }*/
                    
                }                                
            }
            
            Console.WriteLine("*****");
            
            if(1 == 1)
            {
                IList<Contact> contacts = ContactList();
    
                foreach(Contact c in contacts)
                {                    
                    Console.WriteLine("\nContact {0}'s Phone(s): ", c.ContactName);                    
                    
                    // With lazy loading, the c's Phones will not be queried unnecessarily.
                    // The c's Phones will only be queried from database when you access it.
                    // Try to comment/uncomment the following code and see that effect in your RDBMS log file                    .
                    foreach(Phone p in c.Phones)
                    {
                        Console.WriteLine("Phone {0}", p.PhoneNumber);
                    }
                    
                    
                }
            }
            
            
        }

        static ISession OpenSession()
        {
            var c = new Configuration();
            c.AddAssembly(Assembly.GetCallingAssembly());
            ISessionFactory f = c.BuildSessionFactory();
            return f.OpenSession();
        }

        static IList<Phone> PhoneList()
        {
            ISession session = OpenSession();
        
            IQuery query = session.CreateQuery("from Phone p where p.Kontact.ContactName = :_contact_name");
            query.SetParameter("_contact_name", "lennon");
            
            IList<Phone> contacts = query.List<Phone>();

            return contacts;

        
        }
        
        static IList<Contact> ContactList()
        {
            ISession session = OpenSession();

            IQuery query = session.CreateQuery("from Contact");
            
            IList<Contact> contacts = query.List<Contact>();
            
            return contacts;
        }
 
    }

    public class Contact
    {
        public virtual int ContactId { get; set; }
        public virtual string ContactName { get; set; }
        
        public virtual IList<Phone> Phones { get; set; }
        

    }

    public class Phone
    {        
        public virtual Contact Kontact { get; set; }
        public virtual int PhoneId { set; get; }
        public virtual string PhoneNumber { get; set; }
    }


}


Mapping:

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

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" assembly="TestTwoTable" namespace="TestTwoTable">

  <class name="Contact" table="contact">
    <id name="ContactId" column="contact_id">
      <generator class="sequence">
        <param name="sequence">contact_contact_id_seq</param>
      </generator>
    </id>

    <property name="ContactName" column="contact_name"/>
    
    <bag name="Phones" inverse="true">
        <key column="contact_id"/>
        <one-to-many class="Phone"/>
    </bag>

  </class>

  <class name="Phone" table="phone">
    <id name="PhoneId" column="phone_id">
      <generator class="sequence">
        <param name="sequence">phone_phone_id_seq</param>
      </generator>
    </id>

    <property name="PhoneNumber" column="phone_number"/>
    
    <many-to-one name="Kontact" column="contact_id" class="Contact" not-null="true"/>
    
  </class>
  
</hibernate-mapping>

The Database:

CREATE TABLE contact
(
  contact_id serial NOT NULL,
  contact_name text NOT NULL,
  CONSTRAINT contact_pkey PRIMARY KEY (contact_id)
);

CREATE TABLE phone
(
  contact_id integer NOT NULL,
  phone_id serial NOT NULL,
  phone_number text NOT NULL,
  CONSTRAINT phone_pkey PRIMARY KEY (phone_id),
  CONSTRAINT fk_phone__contact FOREIGN KEY (contact_id)
      REFERENCES contact (contact_id)
);


insert into contact(contact_name) values('lennon'),('mccartney');
insert into phone(contact_id, phone_number) values(1,'number nine'),(1,'number 10'),(2,'you know my name, look up the number');


Output:
Phone number nine
Owned by lennon
Phone number 10
Owned by lennon
*****

Contact lennon's Phone(s): 
Phone number nine
Phone number 10

Contact mccartney's Phone(s): 
Phone you know my name, look up the number

No comments:

Post a Comment