How to make this thread-safe

ぐ巨炮叔叔 提交于 2019-12-07 08:08:29

问题


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

回答1:


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


来源:https://stackoverflow.com/questions/5353192/how-to-make-this-thread-safe

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!