Как сделать этот потокобезопасным - PullRequest
4 голосов
/ 18 марта 2011

У меня есть следующая SessionFactory для Fluent NHibernate.

Я получаю ошибку

При создании SessionFactory использовалась недопустимая или неполная конфигурация.

с InnerException

Элемент с тем же ключом уже добавлен.

Эта проблема возникает только изредка, и мое приложение работает нормально в большинстве случаев.время.

На основе NHibernate: System.Argument Исключение: элемент с тем же ключом уже добавлен Я предполагаю, что мой класс не является поточно-ориентированным, что объясняет прерывистую природу этогоошибка.

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;
        }
    }
}

1 Ответ

5 голосов
/ 18 марта 2011

Обычный подход заключается в создании мьютекса (возможно, в вашем публичном методе), который разрешает только один доступ.См. http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx

Не тестируется как компиляция, но что-то вроде:

    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;
    }
...