-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 
Author Message
 Post subject: SessionFactory == Singleton / Session == Session-per-request
PostPosted: Thu Jan 12, 2006 5:51 am 
Newbie

Joined: Sun Jan 08, 2006 2:26 pm
Posts: 15
Hi there,

i got some fundamental questions. An ISessionFactory is expensive to use, so there should be only one for each Database used. In my cases there is just one Database and so i implemented an Singleton-Pattern for this case. Do i need this or is nHibernate managing only one Factory for each Database internally?

Furthermore I´ve read that Sessions are quiet cheap and so i should use a session-per-request. On the other hand i´ve read in that http://www.theserverside.net/articles/s ... ibernateP2 :"Sessions are also expensive to create (though not nearly as expensive as SessionFactories)."

So should i use a session-per-operation and just disconnect the session in each method?

Finally here is my test-code for singleton and session-per-request. Any comments on this are welcome, cause i am not sure if i did the singleton right.



Code:

/// <summary>
   /// Singleton-Pattern for ISession and doing some configuration
   /// </summary>

public class Configure
{
   private Configuration cfg = null;
   private ISessionFactory sessions = null;
   static readonly Configure instance = new Configure();
   static Configure(){}
   
   Configure()
   {
      this.cfg = new Configuration()
         .AddAssembly("NHTest");
      this.sessions = cfg.BuildSessionFactory();
   }
   public static Configure Instance
   {
      get
      {
         return instance;
      }
   }
   public ISessionFactory Sessions
   {
      get
      {
         return sessions;
      }
   }
   public Configuration Cfg
   {
      get
      {
         return cfg;
      }
   }
   public void ErschaffeTabellen(Configuration cfg)
   {
      Console.WriteLine("###### Erstelle Datenbank-Schema! Verwerfe Tabellen und erstelle Neue! #######");
      Console.WriteLine("##############################################################################\n");
         
            
      NHibernate.Tool.hbm2ddl.SchemaExport schemaExport = new NHibernate.Tool.hbm2ddl.SchemaExport(cfg);
      schemaExport.SetOutputFile("schema.txt");
      schemaExport.Create(true, true);
   }

}


class Class1
{   
   /// <summary>
   /// Do some Testing
   /// </summary>
   /// <param name="args"></param>
   [STAThread]
   static void Main(string[] args)
   {
      Configure config = Configure.Instance;
      ISessionFactory fabrik = config.Sessions;
      ISession session = fabrik.OpenSession();
      config.ErschaffeTabellen(config.Cfg);
      FillDB(fabrik);
      //...
   }
   public static void FillDB(ISessionFactory fabrik)
      {
         
         NHibernate.ISession session = null;
         NHibernate.ITransaction transaction = null;
         //...
         // Objects are created here!!!
         //...
         Random rd = new Random();
         
         try
         {
            session = fabrik.OpenSession();
            transaction = session.BeginTransaction();
            for (int i = 0; i < 200; i++)
            {
               // creating 200 objects
               session.Save(newObject);
            }
            // Commit modifications (=> Build and execute queries)
            transaction.Commit();
         }
         catch
         {
            if(transaction != null)
               transaction.Rollback(); // Error => we MUST roll back modifications
            throw; // Here, we throw the same exception so that it is handled (printed)
         }
         finally
         {
            if(session != null)
               session.Close();
         }
      }
}
   



Regards,

Chris


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 13, 2006 2:59 pm 
Senior
Senior

Joined: Fri Jan 13, 2006 2:50 pm
Posts: 123
Location: Blumenau / SC / Brasil
Hi ChrisB.

You've used the singleton pattern to the class Configure, i think you should use it direct to ISessionFactory.

Take a look:

Code:
namespace NHibernate
{
    public class NHibernateSessionFactory
    {
        private static ISessionFactory _sessionFactory;

        // Factory for Sessions. Uses the design pattern Singleton
        public static ISessionFactory GetFactory()
        {
            if (_sessionFactory == null)
            {
                lock (typeof(NHibernateSessionFactory))
                {
                    if (_sessionFactory == null)
                    {
                        Configuration cfg = new Configuration();
                        cfg.AddAssembly("Your assembly");

                        _sessionFactory = cfg.BuildSessionFactory();
                    }
                }
            }

            return _sessionFactory;
        }

        private NHibernateSessionFactory()
        {
        }       
    }
}


To use, you can write something like this:

Code:
ISessionFactory factory = NHibernateSessionFactory.GetFactory();
ISession session = factory.OpenSession();
...


Ps: this code is multi threading (see the use of LOCK).
More info, look here: http://www.dofactory.com/Patterns/PatternSingleton.aspx

Bye!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 14, 2006 6:30 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
If I remember this correctly from another post, this multi-threaded code doesn't actually work and leads to hard-to-detect problems at runtime.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 15, 2006 9:26 pm 
Senior
Senior

Joined: Fri Jan 13, 2006 2:50 pm
Posts: 123
Location: Blumenau / SC / Brasil
sergey wrote:
If I remember this correctly from another post, this multi-threaded code doesn't actually work and leads to hard-to-detect problems at runtime.


Hi sergey. I've got this code from http://www.dofactory.com/Patterns/PatternSingleton.aspx

Bye


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 16, 2006 2:19 am 
Newbie

Joined: Wed Nov 16, 2005 11:01 pm
Posts: 4
I'd be interested in NHibernate users' thoughts on this article:

http://www.yoda.arachsys.com/csharp/singleton.html

Another issue is how to cater for possibility of multiple database access (therefore multiple configuration objects), singleton won't work in this instance, so how to implement?

cheers
si


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 16, 2006 12:08 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
mdsrlz wrote:
Quote:
Hi ChrisB.

You've used the singleton pattern to the class Configure, i think you should use it direct to ISessionFactory.


ChrisB made his own class a singleton, so that through it, he can expose both the NHibernate configuration and the session factory. I do the same. The methods on NHibernate.Cfg.Configuration that return mapping information return different types, with more information, than similar ones on ISession and ISessionFactory.

So far I haven't encountered any issues with doing so. the configuration is read-only after the session factory is created, and I don't attempt to change anything, just keep it around for looking up mapping details. Are there any known issues with doing that?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 16, 2006 7:52 pm 
Senior
Senior

Joined: Wed Jun 15, 2005 4:17 am
Posts: 156
mdsrlz wrote:
sergey wrote:
If I remember this correctly from another post, this multi-threaded code doesn't actually work and leads to hard-to-detect problems at runtime.


Hi sergey. I've got this code from http://www.dofactory.com/Patterns/PatternSingleton.aspx

Bye


Sergey is right. The double-checked locking pattern was declared broken and should not be used. Just google for "double-checked locking" and you will get a lot of info about (and against) it.

cheers,
radu


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 25, 2006 5:35 am 
Regular
Regular

Joined: Fri Jun 11, 2004 6:27 am
Posts: 81
Location: Yaroslavl, Russia
radu wrote:
Sergey is right. The double-checked locking pattern was declared broken and should not be used. Just google for "double-checked locking" and you will get a lot of info about (and against) it.


Widely cited "The Double-Check Locking is Broken" Declaration is not completely correct for .NET world. Microsoft's site tellsthat in .NET double-checking could work as intended. Search for "double-check lock in c#".
At the same time, referenced article is quite old (2002) and it uses a technique that later was considered bad by MS itself. It's locking of type object. Read the following Dr.Gui's article about it. So their example must be rewritten to use static private object to lock onto.

_________________
Best,
Andrew Mayorov // BYTE-force


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 25, 2006 1:15 pm 
Regular
Regular

Joined: Fri Nov 04, 2005 12:37 pm
Posts: 81
Would this do the trick?

Code:
using System;
using NHibernate;
using NHibernate.Cfg;

public sealed class NHibernateSessionFactory
{
   private static volatile ISessionFactory instance;
   private static object syncRoot = new Object();

   private NHibernateSessionFactory() {}

   public static ISessionFactory getFactory()
   {
      
         if (instance == null)
         {
            lock (syncRoot)
            {
               if (instance == null)
               {
                  Configuration cfg = new Configuration();
                  cfg.AddAssembly("vcf");
                  instance = cfg.BuildSessionFactory();
               }
                  
            }
         }

         return instance;
      
   }
}



as outlined here:

http://msdn.microsoft.com/library/defau ... Csharp.asp


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 26, 2006 5:22 am 
Regular
Regular

Joined: Fri Jun 11, 2004 6:27 am
Posts: 81
Location: Yaroslavl, Russia
bosh wrote:
Would this do the trick?
...


As i understand, it should help. Anyway, it seems that in .NET framework the problem could arise only if you have several processors (or hyper-threading).

_________________
Best,
Andrew Mayorov // BYTE-force


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.