SlideShare a Scribd company logo
1 of 8
Download to read offline
TheServerSide.NET - Print Friendly                                                                                          Página 1 de 8




   NHibernate - Part 2                                                                                         Discuss     Printer friendly




  October 12, 2004

  In my last article, I introduced NHibernate, which is an open-source object/relational mapping framework newly available to .NET
  developers. I have been rightly criticized (both here and in other forums) for failing to emphasize that NHibernate is but one of many
  available ORM solutions available, and in fact, the number of open source plus commercial ORM frameworks for .NET is currently
  over 50. As I had to pick one, though, NHibernate was an obvious choice for me since I’ve been doing so much work with Hibernate in
  my life as a consultant. I wanted to explore how that framework made the jump over to .NET and talk about its benefits.

  In this followup article, I want to introduce some more advanced techniques for using NHibernate. Last time, I just walked through
  getting it set up, and introduced a simple application as a demonstration (the University Registration application). This month, the
  goal is to give you some strategies for making NHibernate work with real-world constraints and requirements: high throughput, high
  concurrency applications with special data querying needs.

  To do that, we’ll talk about four major areas: better session management, direct database queries using HQL, lazy loading of object
  collections and direct lifecycle management.

  Session Management
  In my previous article, I showed a rather simple data manager class called RegMgr that implemented a very straightforward version of
  SessionFactory and Session management. Namely, the class created a SessionFactory in the constructor from configuration settings
  and then used that SessionFactory to create a Session for each method. This strategy has several problems with it.

  First, each instance of RegMgr requires a new SessionFactory to be built, which is slow and expensive. A SessionFactory is meant to
  model the entirety of a conversation between your application and a single database; the only reason to have more than one instance of
  SessionFactory is if your application communicates with more than one database. My example application does not, so this is needless
  overhead.

  Secondly, every method has to construct a new Session from the factory. This provides the maximum concurrency protection, as every
  method finishes by closing the open Session and releasing all locks in the database. However, this also finalizes all state in objects
  associated with that Session. Sessions are also expensive to create (though not nearly as expensive as SessionFactories).

  The answer to the first problem is to make sure you only create your SessionFactory once. The original version of RegMgr looked like
  this:

  public class RegMgr : DBMgr
  {
           Configuration config;
           ISessionFactory factory;

              public RegMgr()
              {
                       try
                       {
                                      config = new Configuration();




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2                                                        15/10/2004
TheServerSide.NET - Print Friendly                                                                                               Página 2 de 8


                                        config.AddClass(typeof(nhRegistration.Department));
                                        config.AddClass(typeof(nhRegistration.Person));
                                        config.AddClass(typeof(
                                                 nhRegistration.UniversityClass));
                                        factory = config.BuildSessionFactory();
                           }
                           catch (Exception ex)
                           {
                                    // handle exception
                           }
              }

              // etc...
  }


  The simple fix is to make the factory-related objects static and move the configuration into a static constructor.

  public class RegMgr : DBMgr
  {
           static Configuration config;
           static ISessionFactory factory;

              static RegMgr()
              {
                       try
                       {
                                        config = new Configuration();
                                        config.AddClass(typeof(nhRegistration.Department));
                                        config.AddClass(typeof(nhRegistration.Person));
                                        config.AddClass(typeof(
                                                 nhRegistration.UniversityClass));
                                        factory = config.BuildSessionFactory();
                           }
                           catch (Exception ex)
                           {
                                    // handle exception
                           }
              }

              // etc...
  }


  Now, all methods of all instances of RegMgr share the same SessionFactory, saving your application lots of needless overhead.

  This solution might look like it will work for Session management as well. Why not just add a static Session to the class, and create and
  open it just once in the static constructor? Then, all the methods could use the same Session. The answer is twofold: first, a statically
  shared Session might be accessed by multiple threads concurrently, which could interfere with transactional semantics. Second, a
  statically shared Session will spend most of its life sitting idle, and an idle Session is still holding open a physical database connection.
  Database connections are expensive, rare and valuable. Every data access strategy after server-side cursors has had as a goal
  minimizing the length of time an application holds open a connection, and NHibernate is no different. Therefore, having a static
  Session sitting around open and available is a poor strategy.

  Instead, you can use disconnected Sessions. You can still create a shared Session object (either instance-available or truly static) for
  use in your methods. However, instead of leaving it open, or closing it in every method, you can follow the following pattern:

  public IList getClasses()
  {




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2                                                             15/10/2004
TheServerSide.NET - Print Friendly                                                                                           Página 3 de 8


              IList classes = null;
              try
              {
                       // session is declared in instance scope
                       session.Reconnect();
                       ITransaction tx = session.BeginTransaction();
                       classes = session.CreateCriteria(
                                typeof(UniversityClass)).List();

              }
              catch (Exception ex)
              {
                       // handle exception
              }
              finally
              {
                       session.Flush();
                       session.Disconnect();
  }
              return classes;
  }


  Using this pattern, you can reuse the same Session object, but between method calls you can release the physical resources back to the
  pool which maximizes the concurrency potential of your database but minimizing the overhead to your application.

  HQL
  Sometimes, you are going to need to make more specific requests of NHibernate than simply “give me all the Departments” or “give me
  this Student”. Your application will need to execute arbitrary database queries to provide sophisticated searching and filtering of your
  data. NHibernate provides a facility for this called HQL (the Hibernate Query Language) which looks a lot like SQL. The biggest
  difference between HQL and SQL can be seen in the FROM clause: instead of specifying one or more table names from which to pull
  data, in HQL, you specify one or more classes. Since the point of NHibernate is to provide a transparent data layer via your domain
  objects, it would not make sense to surface the table names in your code. Since your domain objects are already mapped to data tables,
  NHibernate doesn’t need to be fed the table names again.

  For example, in our University registration application, it would be nice to know which classes have been scheduled but do not yet
  have professors assigned to teach them (we’ll need to go round up some first-year grad students to teach those). We’ll create an entry
  point in our RegMgr interface for looking them up:

  public IList getClassesNoProf()
  {}


  We could implement this completely using what we already know about NHibernate:

  IList classes = this.getClasses();
  IList results = new ArrayList();
  foreach(UniversityClass c in classes)
  {
           if(c.Prof == null) results.Add(c);
  }
  return results;


  We can piggyback on the existing method for retrieving all classes in the database, then iterate through them, returning only those that
  meet our criteria. While this works, it is unconscionably slow. We pull every row from the universityclasses table, instantiating an
  object for each, only to throw some, and probably most, of them away. The larger the table, the more egregiously bad this choice
  becomes.

  Instead, we want to do the filtering in the database, which is a platform optimized for this kind of activity and minimizes the amount of




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2                                                         15/10/2004
TheServerSide.NET - Print Friendly                                                                                            Página 4 de 8


  bandwidth required to pipe the results back to our application (since the database is probably on its own server elsewhere on the
  network).

  public IList getClassesNoProf()
  {
           IList results = null;
           try
           {
                    ISession session = factory.OpenSession();
                    results = session.Find(
                             quot;from nhRegistration.UniversityClass as
                             uc where personid is nullquot;);
           }
           catch (Exception ex)
           {
                    // handle exception
           }
           return results;
  }


  The primary access point for implementing an HQL query is the ISession.Find() method. Use this method to execute arbitrary queries.
  HQL supports all major SQL query suffix clauses, like ordering and grouping. To return the same list of UniversityClass instances but
  sorted by the name of the class, we would just change the query slightly:

   results = session.Find(quot;from nhRegistration.UniversityClass as
  uc where personid is null order by uc.Name ascquot;);


  Special note: look at the syntax of the ordering clause. We are sorting by the Name property of UniversityClass which, if you refer
  back to the mapping files from the last article, is mapped to a column named “classname”. When crafting the ordering clause, you can
  refer to this column either by the property name from your domain object or the column name from the database schema, but if you
  choose the property name (sticking with the domain-object-only style) you have to prefix the name of the property with the alias you
  gave to the class name (in this case, “uc”). If you choose to use the column name, you must leave the prefix out (“order by classname
  asc”). I prefer to use the class alias plus property name style, as it maintains the separation between my code and the database.

  By leaving out the normal SQL SELECT clause at the beginning of the query, we have implicitly told NHibernate to return instances of
  the object whose typename appears in the FROM clause. Sometimes you don’t need the whole objects; in this case, all we really want to
  do is display the names of the classes with no professors as a warning to the administrators. Loading and initializing all those instances
  of UniversityClass would be beyond overkill. To overcome this, just include a SELECT clause to return the property you are looking
  for; you will get back an IList containing instances of that property’s type. In our case, an IList of strings:

  public IList getClassNamesNoProf()
  {
           IList results = null;
           try
           {
                    ISession session = factory.OpenSession();
                    results = session.Find(quot;select uc.Name from
                             nhRegistration.UniversityClass as uc
                             where personid is null order by uc.Name ascquot;);
           }
           catch (Exception ex)
           {
                    string s = ex.Message;
           }
           return results;
  }




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2                                                          15/10/2004
TheServerSide.NET - Print Friendly                                                                                             Página 5 de 8



  Conversely, we can return aggregate scalar results as well. Instead of returning the names of the classes that are missing professors, we
  could just return the number of classes missing professors.

  results = session.Find(quot;select count(uc.Name) from
  nhRegistration.UniversityClass as uc where personid is nullquot;);


  As you can see, HQL closely mimics SQL in most ways, except for the substitution of object-oriented descriptors of data elements. For
  most regular object persistence tasks, you can safely ignore HQL, but for more data-centric tasks that can be accomplished faster in the
  database, HQL provides the perfect toolset.

  Lazy Loading
  One of the best things about NHibernate is the way it makes loading related classes utterly transparent; you just ask for the parent
  class, and NHibernate knows enough to go load all the child classes. This is true whether the relationship is one-to-one or one-to-
  many. This could also be one of the worst things about NHibernate, if it was the only option.

  The problem is that this default behavior, while making database usage completely transparent in your code, it can make that usage
  not transparent at all at runtime. By which I mean that any object hierarchy of even moderate size is going to load extremely slowly
  because of all the relationships that have to be navigated.

  Just look at the University Registration domain model as an example. We have only four classes, but loading a single one (an instance
  of Department) causes two separate lists of dependent objects to be loaded, a list of UniversityClasses, and a list of Professors. Mind
  you, each UniversityClass also loads an instance of Professor, and a further list of Students. With enough data in the database, our
  four-class model would already be unwieldy just loading a single Department instance. Now imagine the RegMgr.getAllDepartments()
  method, and the full scope of the problem becomes manifest.

  The solution is lazy loading of collections. Declaring a collection to be lazily initialized is simple – you need only add the attribute
  lazy=”true” to the element declaration. For instance, to make the Classes collection of our Department be lazily loaded, our mapping
  file goes from this:

  <set name=quot;Classesquot; cascade=quot;allquot;>
           <key column=quot;deptidquot;/>
           <one-to-many class=quot;nhRegistration.UniversityClass,
                    nhRegistrationquot;/>
  </set>


  To this:

  <set name=quot;Classesquot; cascade=quot;allquot; lazy=quot;truequot;>
           <key column=quot;deptidquot;/>
           <one-to-many class=quot;nhRegistration.UniversityClass,
                    nhRegistrationquot;/>
  </set>


  Lazy loading means that the elements in the collection are not populated until they are required. You defer the consumption of
  resources dedicated to that task until such time as it is impossible not to. Not only do you defer the resource consumption, you avoid it
  altogether if your execution path never touches the lazy collection. Perhaps the method you are working on only needs to access a
  Department’s classes if the Department has more than one Professor associated with it. For those Department’s that do not meet your
  criteria, you never bother to load all the dependent UniversityClass instances, which is an enormous time saving for your application
  (both at the client and at the database).

  The downside to this powerful technique is that the deferred load requires the original session that loaded the parent object to be used
  to load the lazy collection. If your code follows the pattern we have used for the University Registration application, namely separating
  all data management into a single data manager class, then you can only see the benefits of lazy loading in that data manager class.
  Look at RegMgr.getDepartments() again:

  public IList getDepartments()




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2                                                          15/10/2004
TheServerSide.NET - Print Friendly                                                                                             Página 6 de 8


                       {
              IList depts = null;
              try
              {
                       ISession session = factory.OpenSession();
                       ITransaction tx = session.BeginTransaction();
                       depts = session.CreateCriteria(typeof(Department)).List();
                                session.Close();
              }
              catch (Exception ex)
              {
                       // handle exceptions
              }
              return depts;
  }


  Immediately after we load the Departments, we close the session. With the Classes list marked as lazy, if you attempt to access that
  collection in your business code, you’ll get a LazyInitializationException. This means you can neither access any individual member of
  the collection, nor query any aggregate data, like the total number of members in the collection, because it doesn’t exist yet. And, since
  the session is closed, it never will, unless you attach the parent object to a different session (a different discussion altogether).

  Therefore, you can either move any business logic that would benefit from lazy loading into the data manager, or you can choose not to
  close your session before returning from the method. I suggest that you do not follow the latter course unless you have spent a lot of
  time thinking about the implications, or at least bulletproofing your application through extensive exception handling code.

  Interceptors and Persistent Lifecycle
  There are four major moments in the life of a persistent object. That object can be loaded, updated, saved, or deleted. (Remember, save
  is what happens when a new object is persisted, update happens when you commit changes to an existing object.) Using the code we’ve
  written so far, the only way you can take action at these moments is in the methods of the data manager class that correspond to the
  different activities (getDepartment() or saveStudent() for example). The problem is that these methods live in your data manager, and
  if they need to do anything substantial using the persistent object in question, you have more than likely created too tight a coupling
  between the persistent object and the data manager.

  It would be much cleaner if your objects could handle these lifecycle moments on their own. NHibernate provides an interface that
  your classes can implement that alert NHibernate that instances of the class want to be notified of those lifecycle events. That interface
  is called ILifecycle, and it looks like this:

  public    NHibernate.LifecycleVeto OnUpdate(ISession s){}
  public    void OnLoad(ISession s, object id){}
  public    NHibernate.LifecycleVeto OnSave(ISession s){}
  public    NHibernate.LifecycleVeto OnDelete(ISession s){}

  Three of the four methods give your object a chance to halt further processing of the given lifecycle event by returning a LifecycleVeto.
  Using this mechanism, you can interrogate the internal state of an object prior to saving, updating or deleting it, and if that state
  doesn’t meet some criteria of your application, you can veto the completion of the event. Returning the veto causes the rest of the event
  to fail silently, which means the object isn’t saved, updated or deleted but no notification of that fact is available elsewhere in the
  application. Conversely, you can raise exceptions from these methods which cause them to fail very loudly.

  The original intent of the three veto-able methods was to provide application programmers an alternate means of cascading events to
  dependent objects instead of relying on NHibernate to handle them for you (you get greater control over the details of what events get
  cascaded to which dependent objects). You should NOT use the OnLoad method to load dependent objects, though, as you can
  interfere with NHibernate’s default actions.

  You might be tempted to use these lifecycle events for something like logging, or security. For instance, you could implement this
  interface on every persistent class in your application and, in each method, you could log the event and information about the object to
  a log file. The problem is that you are introducing a lot of repetitive code into your application. The ILifecycle interface is for class-
  specific behavior only. For true cross-cutting concerns, you should create an interceptor instead.




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2                                                          15/10/2004
TheServerSide.NET - Print Friendly                                                                                             Página 7 de 8



  Interceptors are classes that implement the IInterceptor interface. These classes implement the same kinds of lifecycle methods (with
  some additions) but the methods defined on the class are called for that lifecycle event for each and every domain object in the session.
  However, in an interceptor, you can’t veto the events. Instead, you can modify the object and return a Boolean indicating whether or
  not you did. Plus, the number of events is larger on IInterceptor:

  public int[] FindDirty(object entity, object id,
           object[] currentState, object[] previousState, string[]
           propertyNames, NHibernate.Type.IType[] types){}
  public object Instantiate(Type type, object id){}
  public bool OnFlushDirty(object entity, object id, object[]
           currentState, object[] previousState, string[] propertyNames,
           NHibernate.Type.IType[] types){}
  public object IsUnsaved(object entity){}
  public bool OnLoad(object entity, object id, object[] state, string[]
           propertyNames, NHibernate.Type.IType[] types){}
  public bool OnSave(object entity, object id, object[] state, string[]
           propertyNames, NHibernate.Type.IType[] types){}
  public void OnDelete(object entity, object id, object[] state, string[]
           propertyNames, NHibernate.Type.IType[] types){}
  public void PreFlush(System.Collections.ICollection entities){}
  public void PostFlush(System.Collections.ICollection entities){}


  For our University Registration application, I wanted to implement a consistent logging mechanism. To do that, I created a class called
  LoggingInterceptor, which writes out a message to the log whenever an object is loaded or persisted (other unused methods excluded
  for clarity).

  public bool OnLoad(object entity, object id, object[] state, string[]
  propertyNames, NHibernate.Type.IType[] types)
  {
           string msg = string.Format(quot;Instance of {0}, ID: {1} loaded.quot;,
  entity.GetType().Name, id);
           log(msg);
           return false;
  }

  public bool OnSave(object entity, object id, object[] state, string[]
  propertyNames, NHibernate.Type.IType[] types)
  {
           string msg = string.Format(quot;Instance of {0}, ID: {1} saved.quot;,
  entity.GetType().Name, id);
           log(msg);
           return false;
  }

  private void log(string msg)
  {
           // app-specific logging behavior
  }


  The last step to hooking this up is to specify the interceptor when creating the Session that loads the intercepted instances.

  ISession session = factory.OpenSession(new LoggingInterceptor());


  Each and every domain object loaded by this session will now have an interceptor logging all loads and saves.

  Conclusion
  As you can see, there is much more to NHibernate than a few mapping files and a calls to Session.Find(). NHibernate is enormously




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2                                                            15/10/2004
TheServerSide.NET - Print Friendly                                                                                        Página 8 de 8


  flexible. For small, simple applications, you can rely on NHibernate to manage the complexity and redundancy of data access code for
  you, without worrying much about the extended features I’ve covered here. As your application grows in size, complexity and user
  base, though, you will be happy to know that NHibernate provides features that allow you to customize almost everything about the
  way it manages your persistence. We have still barely scratched the surface of what is available.

  Authors

         Justin Gehtland is a founding member of Relevance, LLC, a consultant group dedicated to elevating the practice of software
         development. He is the co-author of Windows Forms Programming in Visual Basic .NET (Addison Wesley, 2003) and
         Effective Visual Basic (Addison Wesley, 2001). Justin is an industry speaker, and instructor with DevelopMentor in the .NET
         curriculum.



                                 News | Discussions | Tech talks | Case studies | Articles | Media kit | Signup | About
                                              All Content Copyright ©2004 TheServerSide Privacy Policy




http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2                                                     15/10/2004

More Related Content

What's hot

Wed 1630 greene_robert_color
Wed 1630 greene_robert_colorWed 1630 greene_robert_color
Wed 1630 greene_robert_colorDATAVERSITY
 
모던자바의 역습
모던자바의 역습모던자바의 역습
모던자바의 역습DoHyun Jung
 
How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...Mario Fusco
 
Advanced Java - Praticals
Advanced Java - PraticalsAdvanced Java - Praticals
Advanced Java - PraticalsFahad Shaikh
 
Pune-Cocoa: Blocks and GCD
Pune-Cocoa: Blocks and GCDPune-Cocoa: Blocks and GCD
Pune-Cocoa: Blocks and GCDPrashant Rane
 
XSLT 3.0 - new features
XSLT 3.0 - new featuresXSLT 3.0 - new features
XSLT 3.0 - new featuresJakub Malý
 
Parallel XSLT Processing of Large XML Documents - XML Prague 2015
Parallel XSLT Processing of Large XML Documents - XML Prague 2015Parallel XSLT Processing of Large XML Documents - XML Prague 2015
Parallel XSLT Processing of Large XML Documents - XML Prague 2015Jakub Malý
 
Blocks & GCD
Blocks & GCDBlocks & GCD
Blocks & GCDrsebbe
 
Lecture02 class -_templatev2
Lecture02 class -_templatev2Lecture02 class -_templatev2
Lecture02 class -_templatev2Hariz Mustafa
 
Java PRACTICAL file
Java PRACTICAL fileJava PRACTICAL file
Java PRACTICAL fileRACHIT_GUPTA
 
Grand Central Dispatch
Grand Central DispatchGrand Central Dispatch
Grand Central Dispatchcqtt191
 
Objective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central DispatchObjective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central DispatchMatteo Battaglio
 
Writing and using Hamcrest Matchers
Writing and using Hamcrest MatchersWriting and using Hamcrest Matchers
Writing and using Hamcrest MatchersShai Yallin
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesGanesh Samarthyam
 

What's hot (20)

Chapter11
Chapter11Chapter11
Chapter11
 
Wed 1630 greene_robert_color
Wed 1630 greene_robert_colorWed 1630 greene_robert_color
Wed 1630 greene_robert_color
 
모던자바의 역습
모던자바의 역습모던자바의 역습
모던자바의 역습
 
Java Programming - 04 object oriented in java
Java Programming - 04 object oriented in javaJava Programming - 04 object oriented in java
Java Programming - 04 object oriented in java
 
iOS Session-2
iOS Session-2iOS Session-2
iOS Session-2
 
Ad java prac sol set
Ad java prac sol setAd java prac sol set
Ad java prac sol set
 
How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...How and why I turned my old Java projects into a first-class serverless compo...
How and why I turned my old Java projects into a first-class serverless compo...
 
Advanced Java - Praticals
Advanced Java - PraticalsAdvanced Java - Praticals
Advanced Java - Praticals
 
Pune-Cocoa: Blocks and GCD
Pune-Cocoa: Blocks and GCDPune-Cocoa: Blocks and GCD
Pune-Cocoa: Blocks and GCD
 
The Java memory model made easy
The Java memory model made easyThe Java memory model made easy
The Java memory model made easy
 
Java Persistence API
Java Persistence APIJava Persistence API
Java Persistence API
 
XSLT 3.0 - new features
XSLT 3.0 - new featuresXSLT 3.0 - new features
XSLT 3.0 - new features
 
Parallel XSLT Processing of Large XML Documents - XML Prague 2015
Parallel XSLT Processing of Large XML Documents - XML Prague 2015Parallel XSLT Processing of Large XML Documents - XML Prague 2015
Parallel XSLT Processing of Large XML Documents - XML Prague 2015
 
Blocks & GCD
Blocks & GCDBlocks & GCD
Blocks & GCD
 
Lecture02 class -_templatev2
Lecture02 class -_templatev2Lecture02 class -_templatev2
Lecture02 class -_templatev2
 
Java PRACTICAL file
Java PRACTICAL fileJava PRACTICAL file
Java PRACTICAL file
 
Grand Central Dispatch
Grand Central DispatchGrand Central Dispatch
Grand Central Dispatch
 
Objective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central DispatchObjective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central Dispatch
 
Writing and using Hamcrest Matchers
Writing and using Hamcrest MatchersWriting and using Hamcrest Matchers
Writing and using Hamcrest Matchers
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
 

Viewers also liked

NHibernate from inside
NHibernate from insideNHibernate from inside
NHibernate from insideAndriy Buday
 
Entity and NHibernate ORM Frameworks Compared
Entity and NHibernate ORM Frameworks ComparedEntity and NHibernate ORM Frameworks Compared
Entity and NHibernate ORM Frameworks ComparedZoltan Iszlai
 
NHibernate - SQLBits IV
NHibernate - SQLBits IVNHibernate - SQLBits IV
NHibernate - SQLBits IVBen Hall
 
Nhibernate Part 1
Nhibernate   Part 1Nhibernate   Part 1
Nhibernate Part 1guest075fec
 
nHibernate Caching
nHibernate CachingnHibernate Caching
nHibernate CachingGuo Albert
 
NHibernate in Action (Parte 1)
NHibernate in Action (Parte 1)NHibernate in Action (Parte 1)
NHibernate in Action (Parte 1)DotNetMarche
 
"ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca...
"ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca..."ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca...
"ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca...Blend Interactive
 
Introduction to NHibernate
Introduction to NHibernateIntroduction to NHibernate
Introduction to NHibernateDublin Alt,Net
 
NHibernate for .NET
NHibernate for .NETNHibernate for .NET
NHibernate for .NETGuo Albert
 
NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)Samnang Chhun
 
Micro orm для жизни. Кожевников Дмитрий D2D Just.NET
Micro orm для жизни. Кожевников Дмитрий D2D Just.NETMicro orm для жизни. Кожевников Дмитрий D2D Just.NET
Micro orm для жизни. Кожевников Дмитрий D2D Just.NETDev2Dev
 
Руйнуємо .NET Міфи
Руйнуємо .NET МіфиРуйнуємо .NET Міфи
Руйнуємо .NET МіфиSerhiy Kalinets
 
Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Alan Christensen
 

Viewers also liked (20)

Hibernate
HibernateHibernate
Hibernate
 
OpenERP 6.0
OpenERP 6.0OpenERP 6.0
OpenERP 6.0
 
NHibernate
NHibernateNHibernate
NHibernate
 
NHibernate from inside
NHibernate from insideNHibernate from inside
NHibernate from inside
 
Entity and NHibernate ORM Frameworks Compared
Entity and NHibernate ORM Frameworks ComparedEntity and NHibernate ORM Frameworks Compared
Entity and NHibernate ORM Frameworks Compared
 
NHibernate - SQLBits IV
NHibernate - SQLBits IVNHibernate - SQLBits IV
NHibernate - SQLBits IV
 
Nhibernate Part 1
Nhibernate   Part 1Nhibernate   Part 1
Nhibernate Part 1
 
nHibernate Caching
nHibernate CachingnHibernate Caching
nHibernate Caching
 
Ddd
DddDdd
Ddd
 
NHibernate in Action (Parte 1)
NHibernate in Action (Parte 1)NHibernate in Action (Parte 1)
NHibernate in Action (Parte 1)
 
"ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca...
"ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca..."ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca...
"ORMs – Entity Framework and NHibernate" - Bob Davidson, South Dakota Code Ca...
 
Introduction to NHibernate
Introduction to NHibernateIntroduction to NHibernate
Introduction to NHibernate
 
NHibernate
NHibernateNHibernate
NHibernate
 
NHibernate
NHibernateNHibernate
NHibernate
 
NHibernate for .NET
NHibernate for .NETNHibernate for .NET
NHibernate for .NET
 
ASP.Net MVC
ASP.Net MVCASP.Net MVC
ASP.Net MVC
 
NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)NHibernate (The ORM For .NET Platform)
NHibernate (The ORM For .NET Platform)
 
Micro orm для жизни. Кожевников Дмитрий D2D Just.NET
Micro orm для жизни. Кожевников Дмитрий D2D Just.NETMicro orm для жизни. Кожевников Дмитрий D2D Just.NET
Micro orm для жизни. Кожевников Дмитрий D2D Just.NET
 
Руйнуємо .NET Міфи
Руйнуємо .NET МіфиРуйнуємо .NET Міфи
Руйнуємо .NET Міфи
 
Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Domain Driven Design Demonstrated
Domain Driven Design Demonstrated
 

Similar to Nhibernate Part 2

Spring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenSpring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenJoshua Long
 
Oleksandr Valetskyy - DI vs. IoC
Oleksandr Valetskyy - DI vs. IoCOleksandr Valetskyy - DI vs. IoC
Oleksandr Valetskyy - DI vs. IoCOleksandr Valetskyy
 
09 Application Design
09 Application Design09 Application Design
09 Application DesignRanjan Kumar
 
Patterns in Python
Patterns in PythonPatterns in Python
Patterns in Pythondn
 
Developing for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQLDeveloping for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQLJohn David Duncan
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxpetabridge
 
Zend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching loggingZend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching loggingTricode (part of Dept)
 
The Naked Bundle - Symfony Live London 2014
The Naked Bundle - Symfony Live London 2014The Naked Bundle - Symfony Live London 2014
The Naked Bundle - Symfony Live London 2014Matthias Noback
 
To Study The Tips Tricks Guidelines Related To Performance Tuning For N Hib...
To Study The Tips Tricks  Guidelines Related To Performance Tuning For  N Hib...To Study The Tips Tricks  Guidelines Related To Performance Tuning For  N Hib...
To Study The Tips Tricks Guidelines Related To Performance Tuning For N Hib...Shahzad
 
.Net Garbage Collector 101
.Net Garbage Collector 101.Net Garbage Collector 101
.Net Garbage Collector 101Woody Pewitt
 
Parallel Programming With Dot Net
Parallel Programming With Dot NetParallel Programming With Dot Net
Parallel Programming With Dot NetNeeraj Kaushik
 
Pro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptPro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptSeok-joon Yun
 
Java design patterns
Java design patternsJava design patterns
Java design patternsShawn Brito
 

Similar to Nhibernate Part 2 (20)

Spring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in HeavenSpring and Cloud Foundry; a Marriage Made in Heaven
Spring and Cloud Foundry; a Marriage Made in Heaven
 
Oleksandr Valetskyy - DI vs. IoC
Oleksandr Valetskyy - DI vs. IoCOleksandr Valetskyy - DI vs. IoC
Oleksandr Valetskyy - DI vs. IoC
 
09 Application Design
09 Application Design09 Application Design
09 Application Design
 
Patterns in Python
Patterns in PythonPatterns in Python
Patterns in Python
 
Developing for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQLDeveloping for Node.JS with MySQL and NoSQL
Developing for Node.JS with MySQL and NoSQL
 
NET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptx
 
Zend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching loggingZend framework 03 - singleton factory data mapper caching logging
Zend framework 03 - singleton factory data mapper caching logging
 
Design Patterns
Design PatternsDesign Patterns
Design Patterns
 
The Naked Bundle - Symfony Live London 2014
The Naked Bundle - Symfony Live London 2014The Naked Bundle - Symfony Live London 2014
The Naked Bundle - Symfony Live London 2014
 
Amazon elastic map reduce
Amazon elastic map reduceAmazon elastic map reduce
Amazon elastic map reduce
 
To Study The Tips Tricks Guidelines Related To Performance Tuning For N Hib...
To Study The Tips Tricks  Guidelines Related To Performance Tuning For  N Hib...To Study The Tips Tricks  Guidelines Related To Performance Tuning For  N Hib...
To Study The Tips Tricks Guidelines Related To Performance Tuning For N Hib...
 
.Net Framework 2 fundamentals
.Net Framework 2 fundamentals.Net Framework 2 fundamentals
.Net Framework 2 fundamentals
 
Java mcq
Java mcqJava mcq
Java mcq
 
.Net Garbage Collector 101
.Net Garbage Collector 101.Net Garbage Collector 101
.Net Garbage Collector 101
 
Parallel Programming With Dot Net
Parallel Programming With Dot NetParallel Programming With Dot Net
Parallel Programming With Dot Net
 
Pro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScriptPro typescript.ch03.Object Orientation in TypeScript
Pro typescript.ch03.Object Orientation in TypeScript
 
Angular Schematics
Angular SchematicsAngular Schematics
Angular Schematics
 
backend
backendbackend
backend
 
backend
backendbackend
backend
 
Java design patterns
Java design patternsJava design patterns
Java design patterns
 

Recently uploaded

My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxnull - The Open Security Community
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 

Recently uploaded (20)

My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 

Nhibernate Part 2

  • 1. TheServerSide.NET - Print Friendly Página 1 de 8 NHibernate - Part 2 Discuss Printer friendly October 12, 2004 In my last article, I introduced NHibernate, which is an open-source object/relational mapping framework newly available to .NET developers. I have been rightly criticized (both here and in other forums) for failing to emphasize that NHibernate is but one of many available ORM solutions available, and in fact, the number of open source plus commercial ORM frameworks for .NET is currently over 50. As I had to pick one, though, NHibernate was an obvious choice for me since I’ve been doing so much work with Hibernate in my life as a consultant. I wanted to explore how that framework made the jump over to .NET and talk about its benefits. In this followup article, I want to introduce some more advanced techniques for using NHibernate. Last time, I just walked through getting it set up, and introduced a simple application as a demonstration (the University Registration application). This month, the goal is to give you some strategies for making NHibernate work with real-world constraints and requirements: high throughput, high concurrency applications with special data querying needs. To do that, we’ll talk about four major areas: better session management, direct database queries using HQL, lazy loading of object collections and direct lifecycle management. Session Management In my previous article, I showed a rather simple data manager class called RegMgr that implemented a very straightforward version of SessionFactory and Session management. Namely, the class created a SessionFactory in the constructor from configuration settings and then used that SessionFactory to create a Session for each method. This strategy has several problems with it. First, each instance of RegMgr requires a new SessionFactory to be built, which is slow and expensive. A SessionFactory is meant to model the entirety of a conversation between your application and a single database; the only reason to have more than one instance of SessionFactory is if your application communicates with more than one database. My example application does not, so this is needless overhead. Secondly, every method has to construct a new Session from the factory. This provides the maximum concurrency protection, as every method finishes by closing the open Session and releasing all locks in the database. However, this also finalizes all state in objects associated with that Session. Sessions are also expensive to create (though not nearly as expensive as SessionFactories). The answer to the first problem is to make sure you only create your SessionFactory once. The original version of RegMgr looked like this: public class RegMgr : DBMgr { Configuration config; ISessionFactory factory; public RegMgr() { try { config = new Configuration(); http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2 15/10/2004
  • 2. TheServerSide.NET - Print Friendly Página 2 de 8 config.AddClass(typeof(nhRegistration.Department)); config.AddClass(typeof(nhRegistration.Person)); config.AddClass(typeof( nhRegistration.UniversityClass)); factory = config.BuildSessionFactory(); } catch (Exception ex) { // handle exception } } // etc... } The simple fix is to make the factory-related objects static and move the configuration into a static constructor. public class RegMgr : DBMgr { static Configuration config; static ISessionFactory factory; static RegMgr() { try { config = new Configuration(); config.AddClass(typeof(nhRegistration.Department)); config.AddClass(typeof(nhRegistration.Person)); config.AddClass(typeof( nhRegistration.UniversityClass)); factory = config.BuildSessionFactory(); } catch (Exception ex) { // handle exception } } // etc... } Now, all methods of all instances of RegMgr share the same SessionFactory, saving your application lots of needless overhead. This solution might look like it will work for Session management as well. Why not just add a static Session to the class, and create and open it just once in the static constructor? Then, all the methods could use the same Session. The answer is twofold: first, a statically shared Session might be accessed by multiple threads concurrently, which could interfere with transactional semantics. Second, a statically shared Session will spend most of its life sitting idle, and an idle Session is still holding open a physical database connection. Database connections are expensive, rare and valuable. Every data access strategy after server-side cursors has had as a goal minimizing the length of time an application holds open a connection, and NHibernate is no different. Therefore, having a static Session sitting around open and available is a poor strategy. Instead, you can use disconnected Sessions. You can still create a shared Session object (either instance-available or truly static) for use in your methods. However, instead of leaving it open, or closing it in every method, you can follow the following pattern: public IList getClasses() { http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2 15/10/2004
  • 3. TheServerSide.NET - Print Friendly Página 3 de 8 IList classes = null; try { // session is declared in instance scope session.Reconnect(); ITransaction tx = session.BeginTransaction(); classes = session.CreateCriteria( typeof(UniversityClass)).List(); } catch (Exception ex) { // handle exception } finally { session.Flush(); session.Disconnect(); } return classes; } Using this pattern, you can reuse the same Session object, but between method calls you can release the physical resources back to the pool which maximizes the concurrency potential of your database but minimizing the overhead to your application. HQL Sometimes, you are going to need to make more specific requests of NHibernate than simply “give me all the Departments” or “give me this Student”. Your application will need to execute arbitrary database queries to provide sophisticated searching and filtering of your data. NHibernate provides a facility for this called HQL (the Hibernate Query Language) which looks a lot like SQL. The biggest difference between HQL and SQL can be seen in the FROM clause: instead of specifying one or more table names from which to pull data, in HQL, you specify one or more classes. Since the point of NHibernate is to provide a transparent data layer via your domain objects, it would not make sense to surface the table names in your code. Since your domain objects are already mapped to data tables, NHibernate doesn’t need to be fed the table names again. For example, in our University registration application, it would be nice to know which classes have been scheduled but do not yet have professors assigned to teach them (we’ll need to go round up some first-year grad students to teach those). We’ll create an entry point in our RegMgr interface for looking them up: public IList getClassesNoProf() {} We could implement this completely using what we already know about NHibernate: IList classes = this.getClasses(); IList results = new ArrayList(); foreach(UniversityClass c in classes) { if(c.Prof == null) results.Add(c); } return results; We can piggyback on the existing method for retrieving all classes in the database, then iterate through them, returning only those that meet our criteria. While this works, it is unconscionably slow. We pull every row from the universityclasses table, instantiating an object for each, only to throw some, and probably most, of them away. The larger the table, the more egregiously bad this choice becomes. Instead, we want to do the filtering in the database, which is a platform optimized for this kind of activity and minimizes the amount of http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2 15/10/2004
  • 4. TheServerSide.NET - Print Friendly Página 4 de 8 bandwidth required to pipe the results back to our application (since the database is probably on its own server elsewhere on the network). public IList getClassesNoProf() { IList results = null; try { ISession session = factory.OpenSession(); results = session.Find( quot;from nhRegistration.UniversityClass as uc where personid is nullquot;); } catch (Exception ex) { // handle exception } return results; } The primary access point for implementing an HQL query is the ISession.Find() method. Use this method to execute arbitrary queries. HQL supports all major SQL query suffix clauses, like ordering and grouping. To return the same list of UniversityClass instances but sorted by the name of the class, we would just change the query slightly: results = session.Find(quot;from nhRegistration.UniversityClass as uc where personid is null order by uc.Name ascquot;); Special note: look at the syntax of the ordering clause. We are sorting by the Name property of UniversityClass which, if you refer back to the mapping files from the last article, is mapped to a column named “classname”. When crafting the ordering clause, you can refer to this column either by the property name from your domain object or the column name from the database schema, but if you choose the property name (sticking with the domain-object-only style) you have to prefix the name of the property with the alias you gave to the class name (in this case, “uc”). If you choose to use the column name, you must leave the prefix out (“order by classname asc”). I prefer to use the class alias plus property name style, as it maintains the separation between my code and the database. By leaving out the normal SQL SELECT clause at the beginning of the query, we have implicitly told NHibernate to return instances of the object whose typename appears in the FROM clause. Sometimes you don’t need the whole objects; in this case, all we really want to do is display the names of the classes with no professors as a warning to the administrators. Loading and initializing all those instances of UniversityClass would be beyond overkill. To overcome this, just include a SELECT clause to return the property you are looking for; you will get back an IList containing instances of that property’s type. In our case, an IList of strings: public IList getClassNamesNoProf() { IList results = null; try { ISession session = factory.OpenSession(); results = session.Find(quot;select uc.Name from nhRegistration.UniversityClass as uc where personid is null order by uc.Name ascquot;); } catch (Exception ex) { string s = ex.Message; } return results; } http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2 15/10/2004
  • 5. TheServerSide.NET - Print Friendly Página 5 de 8 Conversely, we can return aggregate scalar results as well. Instead of returning the names of the classes that are missing professors, we could just return the number of classes missing professors. results = session.Find(quot;select count(uc.Name) from nhRegistration.UniversityClass as uc where personid is nullquot;); As you can see, HQL closely mimics SQL in most ways, except for the substitution of object-oriented descriptors of data elements. For most regular object persistence tasks, you can safely ignore HQL, but for more data-centric tasks that can be accomplished faster in the database, HQL provides the perfect toolset. Lazy Loading One of the best things about NHibernate is the way it makes loading related classes utterly transparent; you just ask for the parent class, and NHibernate knows enough to go load all the child classes. This is true whether the relationship is one-to-one or one-to- many. This could also be one of the worst things about NHibernate, if it was the only option. The problem is that this default behavior, while making database usage completely transparent in your code, it can make that usage not transparent at all at runtime. By which I mean that any object hierarchy of even moderate size is going to load extremely slowly because of all the relationships that have to be navigated. Just look at the University Registration domain model as an example. We have only four classes, but loading a single one (an instance of Department) causes two separate lists of dependent objects to be loaded, a list of UniversityClasses, and a list of Professors. Mind you, each UniversityClass also loads an instance of Professor, and a further list of Students. With enough data in the database, our four-class model would already be unwieldy just loading a single Department instance. Now imagine the RegMgr.getAllDepartments() method, and the full scope of the problem becomes manifest. The solution is lazy loading of collections. Declaring a collection to be lazily initialized is simple – you need only add the attribute lazy=”true” to the element declaration. For instance, to make the Classes collection of our Department be lazily loaded, our mapping file goes from this: <set name=quot;Classesquot; cascade=quot;allquot;> <key column=quot;deptidquot;/> <one-to-many class=quot;nhRegistration.UniversityClass, nhRegistrationquot;/> </set> To this: <set name=quot;Classesquot; cascade=quot;allquot; lazy=quot;truequot;> <key column=quot;deptidquot;/> <one-to-many class=quot;nhRegistration.UniversityClass, nhRegistrationquot;/> </set> Lazy loading means that the elements in the collection are not populated until they are required. You defer the consumption of resources dedicated to that task until such time as it is impossible not to. Not only do you defer the resource consumption, you avoid it altogether if your execution path never touches the lazy collection. Perhaps the method you are working on only needs to access a Department’s classes if the Department has more than one Professor associated with it. For those Department’s that do not meet your criteria, you never bother to load all the dependent UniversityClass instances, which is an enormous time saving for your application (both at the client and at the database). The downside to this powerful technique is that the deferred load requires the original session that loaded the parent object to be used to load the lazy collection. If your code follows the pattern we have used for the University Registration application, namely separating all data management into a single data manager class, then you can only see the benefits of lazy loading in that data manager class. Look at RegMgr.getDepartments() again: public IList getDepartments() http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2 15/10/2004
  • 6. TheServerSide.NET - Print Friendly Página 6 de 8 { IList depts = null; try { ISession session = factory.OpenSession(); ITransaction tx = session.BeginTransaction(); depts = session.CreateCriteria(typeof(Department)).List(); session.Close(); } catch (Exception ex) { // handle exceptions } return depts; } Immediately after we load the Departments, we close the session. With the Classes list marked as lazy, if you attempt to access that collection in your business code, you’ll get a LazyInitializationException. This means you can neither access any individual member of the collection, nor query any aggregate data, like the total number of members in the collection, because it doesn’t exist yet. And, since the session is closed, it never will, unless you attach the parent object to a different session (a different discussion altogether). Therefore, you can either move any business logic that would benefit from lazy loading into the data manager, or you can choose not to close your session before returning from the method. I suggest that you do not follow the latter course unless you have spent a lot of time thinking about the implications, or at least bulletproofing your application through extensive exception handling code. Interceptors and Persistent Lifecycle There are four major moments in the life of a persistent object. That object can be loaded, updated, saved, or deleted. (Remember, save is what happens when a new object is persisted, update happens when you commit changes to an existing object.) Using the code we’ve written so far, the only way you can take action at these moments is in the methods of the data manager class that correspond to the different activities (getDepartment() or saveStudent() for example). The problem is that these methods live in your data manager, and if they need to do anything substantial using the persistent object in question, you have more than likely created too tight a coupling between the persistent object and the data manager. It would be much cleaner if your objects could handle these lifecycle moments on their own. NHibernate provides an interface that your classes can implement that alert NHibernate that instances of the class want to be notified of those lifecycle events. That interface is called ILifecycle, and it looks like this: public NHibernate.LifecycleVeto OnUpdate(ISession s){} public void OnLoad(ISession s, object id){} public NHibernate.LifecycleVeto OnSave(ISession s){} public NHibernate.LifecycleVeto OnDelete(ISession s){} Three of the four methods give your object a chance to halt further processing of the given lifecycle event by returning a LifecycleVeto. Using this mechanism, you can interrogate the internal state of an object prior to saving, updating or deleting it, and if that state doesn’t meet some criteria of your application, you can veto the completion of the event. Returning the veto causes the rest of the event to fail silently, which means the object isn’t saved, updated or deleted but no notification of that fact is available elsewhere in the application. Conversely, you can raise exceptions from these methods which cause them to fail very loudly. The original intent of the three veto-able methods was to provide application programmers an alternate means of cascading events to dependent objects instead of relying on NHibernate to handle them for you (you get greater control over the details of what events get cascaded to which dependent objects). You should NOT use the OnLoad method to load dependent objects, though, as you can interfere with NHibernate’s default actions. You might be tempted to use these lifecycle events for something like logging, or security. For instance, you could implement this interface on every persistent class in your application and, in each method, you could log the event and information about the object to a log file. The problem is that you are introducing a lot of repetitive code into your application. The ILifecycle interface is for class- specific behavior only. For true cross-cutting concerns, you should create an interceptor instead. http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2 15/10/2004
  • 7. TheServerSide.NET - Print Friendly Página 7 de 8 Interceptors are classes that implement the IInterceptor interface. These classes implement the same kinds of lifecycle methods (with some additions) but the methods defined on the class are called for that lifecycle event for each and every domain object in the session. However, in an interceptor, you can’t veto the events. Instead, you can modify the object and return a Boolean indicating whether or not you did. Plus, the number of events is larger on IInterceptor: public int[] FindDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types){} public object Instantiate(Type type, object id){} public bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types){} public object IsUnsaved(object entity){} public bool OnLoad(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types){} public bool OnSave(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types){} public void OnDelete(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types){} public void PreFlush(System.Collections.ICollection entities){} public void PostFlush(System.Collections.ICollection entities){} For our University Registration application, I wanted to implement a consistent logging mechanism. To do that, I created a class called LoggingInterceptor, which writes out a message to the log whenever an object is loaded or persisted (other unused methods excluded for clarity). public bool OnLoad(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types) { string msg = string.Format(quot;Instance of {0}, ID: {1} loaded.quot;, entity.GetType().Name, id); log(msg); return false; } public bool OnSave(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types) { string msg = string.Format(quot;Instance of {0}, ID: {1} saved.quot;, entity.GetType().Name, id); log(msg); return false; } private void log(string msg) { // app-specific logging behavior } The last step to hooking this up is to specify the interceptor when creating the Session that loads the intercepted instances. ISession session = factory.OpenSession(new LoggingInterceptor()); Each and every domain object loaded by this session will now have an interceptor logging all loads and saves. Conclusion As you can see, there is much more to NHibernate than a few mapping files and a calls to Session.Find(). NHibernate is enormously http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2 15/10/2004
  • 8. TheServerSide.NET - Print Friendly Página 8 de 8 flexible. For small, simple applications, you can rely on NHibernate to manage the complexity and redundancy of data access code for you, without worrying much about the extended features I’ve covered here. As your application grows in size, complexity and user base, though, you will be happy to know that NHibernate provides features that allow you to customize almost everything about the way it manages your persistence. We have still barely scratched the surface of what is available. Authors Justin Gehtland is a founding member of Relevance, LLC, a consultant group dedicated to elevating the practice of software development. He is the co-author of Windows Forms Programming in Visual Basic .NET (Addison Wesley, 2003) and Effective Visual Basic (Addison Wesley, 2001). Justin is an industry speaker, and instructor with DevelopMentor in the .NET curriculum. News | Discussions | Tech talks | Case studies | Articles | Media kit | Signup | About All Content Copyright ©2004 TheServerSide Privacy Policy http://www.theserverside.net/articles/printfriendly.tss?id=NHibernateP2 15/10/2004