SessionFactory线程安全问题

时间:2013-08-14 08:15:58

标签: nhibernate thread-safety singleton ninject sessionfactory

有时我会在我的网络应用程序中获得此错误堆栈跟踪:

   [ArgumentException: An item with the same key has already been added.]
   System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) +52
   System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) +10695474
   System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value) +10
   NHibernate.Util.ThreadSafeDictionary`2.Add(TKey key, TValue value) +93
   NHibernate.Type.TypeFactory.GetType(NullableType defaultUnqualifiedType, Int32 length, GetNullableTypeWithLength ctorDelegate) +88
   NHibernate.Type.TypeFactory.<RegisterDefaultNetTypes>b__c(Int32 l) +82
   NHibernate.Type.TypeFactory.BuiltInType(String typeName, Int32 length) +46
   NHibernate.Mapping.SimpleValue.GetHeuristicType() +168
   NHibernate.Mapping.SimpleValue.get_Type() +49
   NHibernate.Mapping.SimpleValue.IsValid(IMapping mapping) +30
   NHibernate.Mapping.PersistentClass.Validate(IMapping mapping) +87
   NHibernate.Mapping.RootClass.Validate(IMapping mapping) +21
   NHibernate.Cfg.Configuration.ValidateEntities() +183
   NHibernate.Cfg.Configuration.Validate() +13
   NHibernate.Cfg.Configuration.BuildSessionFactory() +36
   Framework.Data.Code.BaseSessionFactoryProvider..ctor() +74
   Framework.Data.Code.SessionFactoryProvider..ctor() +29
   Framework.Data.Code.NestedSessionManager..cctor() +43

我的SessionFactoryProvider是线程安全的单例:

 public interface ISessionFactoryProvider
 {
        ISessionFactory GetSessionFactory();
 }
 public abstract class BaseSessionFactoryProvider : ISessionFactoryProvider
 {
        protected readonly ISessionFactory factory;
        public ISessionFactory GetSessionFactory()
        {
            return factory;
        }

        protected BaseSessionFactoryProvider()
        {
            factory = GetConfig().BuildSessionFactory();
        }
        public abstract Configuration GetConfig();
 }
 public class SessionFactoryProvider : BaseSessionFactoryProvider
 {
            public static ISessionFactory SessionFactory
            {
                get { return Instance.factory; }
            }
            public override Configuration GetConfig()
            {
                return new Configuration().Configure();
            }
            public static SessionFactoryProvider Instance
            {
                get
                {
                    return NestedSessionManager.sessionManager;
                }
            }
            class NestedSessionManager
            {
                internal static readonly SessionFactoryProvider sessionManager =
                    new SessionFactoryProvider();
            }
   }

同样在我的应用程序中,我通过ninject将SessionFactoryProvider绑定到ISessionFactoryProvider kernel.Bind<ISessionFactoryProvider>().To<SessionFactoryProvider>().InSingletonScope();

所以我的问题为什么会出现这个错误?

1 个答案:

答案 0 :(得分:0)

在我的评论中,我说我看到你的Singleton实现没有任何缺陷。 实际上,有一个显而易见的问题:您的SessionFactoryProvider无参数构造函数不是私有的,因为SessionFactoryProvider的构造函数没有任何重载。

因此,编译器为SessionFactoryProvider生成一个公共无参数构造函数 见Should we always include a default constructor in the class?

因此,任何代码都可以实例化新的SessionFactoryProvider 这个公共构造函数(这应该很容易测试),Ninject使用它来实例化类。 (这让我感到困惑:Ninject如何实例化该类?它不应该能够在没有公共构造函数的情况下实例化一个类)。 我想这就是你最后的重复SessionFactoryProvider

您应该使用公共构造函数实现SessionFactoryProvider,而不考虑单例实现。然后只依靠Ninject及其InSingletonScope()来提供单例函数