Page 1 of 1

Fluent NHibernate tutorial PART 2 Simple ORM application (DAO classes)

#1 FlashM  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 382
  • View blog
  • Posts: 1,195
  • Joined: 03-December 09

Posted 18 March 2010 - 01:02 PM

In this tutorial we are going to extend the application that we created in my previous Fluent NHibernate tutorial (you can find it here: http://www.dreaminco...howtopic=161638)

This tutorial will focus on creating DAO classes, but first let's see what DAO even stands for...


DATA ACCESS OBJECT

In computer software, a Data Access Object (DAO) is an object that provides an abstract interface to some type of database or persistence mechanism, providing some specific operations without exposing details of the database. It provides a mapping from application calls to the persistence layer. This isolation separates the concerns of what data accesses the application needs, in terms of domain-specific objects and data types (the public interface of the DAO), and how these needs can be satisfied with a specific DBMS, database schema, etc. (the implementation of the DAO). This design pattern is equally applicable to most programming languages, most types of software with persistence needs and most types of database.

ADVANTAGES

  • Relatively simple and rigorous separation between two important parts of an application which can and should know almost nothing of each other, and which can be expected to evolve frequently and independently.
  • Changing business logic can rely on the same DAO interface, while changes to persistence logic does not affect DAO clients as long as the interface remains correctly implemented.
  • Improved efficiency and performance of the data layer since it is standard reusable software.
  • It is also expected that in case the DAO implementation were to change the other parts of the application would be unaffected.


More info about Data access object can be found at: http://en.wikipedia....a_access_object


Now, let's leave the theory aside and do some concrete example. Open up the solution created in our previous tutorial. In the solution explorer, select the folder named Model and create two new sub folders named Entities and DaoClasses. Now grab the two classes (Employee.cs and Post.cs) and move them into this newly created Entities sub folder. By moving them to a sub folder, their namespace (SimpleOrmApplication.Model) remains the same and lets leave that as it is because there is no need to change it.


Now your folder structure should look exactly like this:

Attached Image


Now that we have prepared everything that we need, let's create a DAO class for each and every entity found in our Entities folder. Right click on the DaoClasses folder and add two new classes named EmployeeDao and PostDao.


Attached Image


Update the EmployeeDao class to look like this:


using System;
using System.Collections.Generic;
using NHibernate;

namespace SimpleOrmApplication.Model.DaoClasses
{
    public class EmployeeDao
    {
        public static Employee Get(ISession session, int id)
        {
            return session.Get<Employee>(id);
        }

        public static void Save(ISession session, Employee employee)
        {
            if (employee == null)
                throw new ArgumentNullException("employee must not be null!");

            session.Save(employee);
        }

        public static void Delete(ISession session, Employee employee)
        {
            if (employee == null)
                throw new ArgumentNullException("employee must not be null!");

            session.Delete(employee);
        }

        public static IList<Employee> ListAll(ISession session)
        {
            return session
                .CreateCriteria(typeof(Employee))
                .List<Employee>();
        }
    }
}




Update the PostDao class to look like this:


using System;
using System.Collections.Generic;
using NHibernate;
using NHibernate.Criterion;

namespace SimpleOrmApplication.Model.DaoClasses
{
    public class PostDao
    {
        public static Post Get(ISession session, int id)
        {
            return session.Get<Post>(id);
        }

        public static void Save(ISession session, Post post)
        {
            if (post == null)
                throw new ArgumentNullException("post must not be null!");

            session.Save(post);
        }

        public static void Delete(ISession session, Post post)
        {
            if (post == null)
                throw new ArgumentNullException("employee must not be null!");

            session.Delete(post);
        }

        public static IList<Post> ListAll(ISession session)
        {
            return session
                .CreateCriteria(typeof(Post))
                .List<Post>();
        }

        public static Post GetByName(ISession session, string name)
        {
            return session.CreateCriteria(typeof(Post))
                .Add(Expression.Eq("PostName", name))
                .UniqueResult<Post>();
        }
    }
}



Notice that both of our dao classes are in SimpleOrmApplication.Model.DaoClasses namespace and they should be in different namespace than our entity classes. If they were in the same namespace as entities, our CreateMappings method (method from previous tutorial) would try to create auto mappings for dao classes as well and it would fail. Also all the methods in dao classes are marked as static, so we don't need to create a new instance if this class to call the methods. You will also need to add the following using statement to your Form1.cs class:


using SimpleOrmApplication.Model.DaoClasses;





Now let's update the btnDoSomeStuff_Click method to use our newly created dao classes. The code in button click event should look something like this:


private void btnDoSomeStuff_Click(object sender, EventArgs e)
{
    using (ISession session = sessionFactory.OpenSession())
    {
        using (ITransaction transaction = session.BeginTransaction())
        {
            Post p1 = new Post();
            p1.PostCode = "1000";
            p1.PostName = "Ljubljana";

            Post p2 = new Post();
            p2.PostCode = "2000";
            p2.PostName = "Maribor";


            Employee emp = new Employee();
            emp.FirstName = "Alex";
            emp.LastName = "Kecman";
            emp.Address = "Sarhova 34";
            emp.Post = p1;
            emp.DateEmployed = DateTime.Now;

            EmployeeDao.Save(session, emp);
            PostDao.Save(session, p1);
            PostDao.Save(session, p2);

            transaction.Commit();
        }
    }
}




Now add three new buttons to our form named btnGetPost, btnListEmployees and btnDeletePost.


Update the btnGetPost_Click method to look like this:
private void btnGetPost_Click(object sender, EventArgs e)
{
    //We don't need transaction here since we are not saving, updating
    //or deleting an entity.
    using (ISession session = sessionFactory.OpenSession())
    {
        Post p = PostDao.GetByName(session, "Maribor");
    }
}




Update the btnListEmployees_Click method to look like this:
private void btnListEmployees_Click(object sender, EventArgs e)
{
    using (ISession session = sessionFactory.OpenSession())
    {
        //We don't need transaction here since we are not saving, updating
        //or deleting an entity.
        IList<Employee> emps = EmployeeDao.ListAll(session);
    }
}




Update the btnDeletePost_Click method to look like this:
private void btnDeletePost_Click(object sender, EventArgs e)
{
    using (ISession session = sessionFactory.OpenSession())
    {
        //We need to use transaction here, since we are deleting an entity
        //Do not forget to commit transaction, so the changes are persisted
        //into database.
        using (ITransaction transaction = session.BeginTransaction())
        {
            Post p = PostDao.Get(session, 2);
            PostDao.Delete(session, p);

            transaction.Commit();
        }
    }
}




It is possible that we do not use a transaction when deleting an entity, but then we would have to update our Delete method in dao class to look like this:
public static void Delete(ISession session, Post post)
{
    if (post == null)
        throw new ArgumentNullException("employee must not be null!");

    session.Delete(post);
    session.Flush();
}




Notice the session.Flush() is called after the delete method. This statement persist our deleted entity into database. Now our btnDeletePost_Click method could look like this:

private void btnDeletePost_Click(object sender, EventArgs e)
{
    using (ISession session = sessionFactory.OpenSession())
    {
        Post p = PostDao.Get(session, 1);
        PostDao.Delete(session, p);
    }
}




Hope you enjoyed this tutorial. If anything unclear feel free to ask...

Is This A Good Question/Topic? 0
  • +

Replies To: Fluent NHibernate tutorial PART 2

#2 Guest_Fluent Newbie*


Reputation:

Posted 08 February 2011 - 11:53 PM

I find these Dao classes a bit redundant, I would prefer to use the session object directly, and how would this handle transactions being passed through methods?
It all just seems a bit repetitive, writing more code for minimal benefit.
I don't see how
EmployeeDao.Save(session, emp)
is better than
session.Save<Employee>(emp);


if anything finder/helper/dao methods could be added to the actual employee class via partial classes.

loved your firt tutorial btw.
Was This Post Helpful? 0

#3 FlashM  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 382
  • View blog
  • Posts: 1,195
  • Joined: 03-December 09

Posted 09 February 2011 - 12:36 AM

You're absolutely right! :-)
Was This Post Helpful? 0
  • +
  • -

#4 Guest_Gustavo*


Reputation:

Posted 16 February 2011 - 02:21 PM

Hi,

I'm really new to Nhibernate and Fluent -NH. (I used to use PHP Propel ORM, which is very similar to NHibernate)

Is it mandatory to pass this ISession variable as a parameter in every methods in our DAO classes? Can we implement something like a "Singleton Connection class"?

Anyway, these two tutorials helped me a lot, thanks!
Was This Post Helpful? 0

#5 FlashM  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 382
  • View blog
  • Posts: 1,195
  • Joined: 03-December 09

Posted 20 May 2011 - 12:02 AM

No, it's not necessary... This is more like a beginner's tutorial... I usually create ISession instance inside each method in Dao classes...
Was This Post Helpful? 0
  • +
  • -

#6 nighttrain  Icon User is online

  • D.I.C Regular

Reputation: 7
  • Posts: 339
  • Joined: 22-September 10

Posted 07 March 2012 - 06:45 AM

I just got a question I did it at all, I have created a database and then I have tried to do:

Post p = PostDao.GetByName(session, "Maribor");
                var i = p;
                string h = p.ToString();
                MessageBox.Show(p.ToString() + " " + h.ToString());



but it has been retreived an error in this function:
public static Post GetByName(ISession session, string name)
        {
            return 
                session.CreateCriteria(typeof(Post))
                .Add(Expression.Eq("PostName", name))
                .UniqueResult<Post>();
        }



Error :
NonUniqueResultException was unhandled
query did not return a unique result: 4



Anyone is known how to fix that?

regards
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1