开发者

How to make this thread-safe

I have the following SessionFactory for Fluent NHibernate.

I am getting an error of

An invalid or incomplete configuration was used while creating a SessionFactory.

with an InnerException of

An item with the same key has already been added.

This problem is only happening occasionally and my application works fine most of the time.

Based on NHibernate: System.Argument Exception : An item with the same key has already been added I'm guessing my class is not thread-safe which would explain the intermittent nature of this error.

using System;
using NHibernate;
using NHibernate.Cache;
using NHibernate.Cfg;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using WSS.Data.Domain;

namespace WSS.Data {
    public static class SessionFactory {
        private static ISessionFactory _factory = null;
        private static ISessionFactory GetFactory() {
            if (_factory == null) {
                NHibernate.Cfg.Configuration config;
                config = new NHibernate.Cfg.Configuration();
                config.Configure();
                if (config == null) {
                    throw new InvalidOperationException("NHibernate configuration is null.");
                }


                config.AddAssembly("WSS.Data");
                _factory = config.BuildSessionFactory();
                if (_factory == null) {
                    throw new InvalidOperationException("Call to Configuration.BuildSessionFactory() returned null.");
                }
            }
            return _factory;

        }

        private static ISessionFactory GetFluentFactory() {
            if(_factory == null) {
                _factory = Fluently.Configure()
                    .Database(开发者_如何转开发MsSqlConfiguration.MsSql2000
                        .ConnectionString(c => c
                            .Is(ConnectionStrings.Auto))
                        .Cache(c => c
                            .UseQueryCache()
                            .ProviderClass())
                        .ShowSql())
                    .Mappings(m => m
                        .FluentMappings.AddFromAssemblyOf())
                    .BuildSessionFactory();
            }

            return _factory;
        }

        public static ISession OpenSession() {
            ISession session;
            session = GetFluentFactory().OpenSession();
            if (session == null) {
                throw new InvalidOperationException("Call to factory.OpenSession() returned null.");
            }
            return session;
        }
    }
}


The usual approach is to create a mutex (probably in your public method) that only allows single access. See http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx

Not tested as compiling, but something like:

    private static Mutex _sessionMutex = new Mutex();

    public static ISession OpenSession() {
        ISession session;

        _sessionMutex.WaitOne();

        session = GetFluentFactory().OpenSession();
        if (session == null) {
            throw new InvalidOperationException("Call to factory.OpenSession() returned null.");
        }

        _sessionMutex.ReleaseMutex();
        return session;
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜