Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
212 views
in Technique[技术] by (71.8m points)

c# - Ensure NHibernate SessionFactory is only created once

I have written an NHibernateSessionFactory class which holds a static Nhibernate ISessionFactory. This is used to make sure we only have one session factory, and the first time OpenSession() is called I create the actuall SessionFactory - next times I use the same and open a session on it. The code looks like this:

public class NhibernateSessionFactory : INhibernateSessionFactory
{
    private static ISessionFactory _sessionFactory;

    public ISession OpenSession()
    {
        if (_sessionFactory == null)
        {
            var cfg = Fluently.Configure().
                Database(SQLiteConfiguration.Standard.ShowSql().UsingFile("Foo.db")).
                Mappings(m => m.FluentMappings.AddFromAssemblyOf<MappingsPersistenceModel>());
            _sessionFactory = cfg.BuildSessionFactory();
            BuildSchema(cfg);
        }
        return _sessionFactory.OpenSession();
    }

    private static void BuildSchema(FluentConfiguration configuration)
    {
        var sessionSource = new SessionSource(configuration);
        var session = sessionSource.CreateSession();
        sessionSource.BuildSchema(session);            
    }
}

Now I have a problem. My application is split between client and server. The Nhibernate stuff is on the server side. On startup both my client and server wants to access the database through some services which will use the NhibernateSessionFactory. Result is a race condition to whether the _sessionFactory is created before the request comes from the client. If it isn't it will fail..

I guess I need some sort of queueing or wait mechanism in the NhibernateSessionFactory, but I'm not sure about what to do. Anyone had the same problem before? What's the best solution?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The sessionFactory must be a thread-safe singleton.

A common pattern in Java is to build the sessionFactory in a static initializer. See HibernateUtil. You can do the same in C#.

There are other patterns to implement singleton, including the usage of lock or synchronized sections. Here is slight variant that should solve your problem if I understood it correctly.

static readonly object factorylock = new object();

public ISession OpenSession()
{
    lock (factorylock)
    {
       if (_sessionFactory == null)
       {
            var cfg = Fluently.Configure().
               Database(SQLiteConfiguration.Standard.ShowSql().UsingFile("Foo.db")).
               Mappings(m => m.FluentMappings.AddFromAssemblyOf<MappingsPersistenceModel>());
            _sessionFactory = cfg.BuildSessionFactory();
            BuildSchema(cfg);
        }
    }
    return _sessionFactory.OpenSession();
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...