views:

273

answers:

1

Hi There, I have created an multi thread application on IIS (ASP.NET MVC), When the threading server started it creates 10 thread and it's execting workitems into the threads.

Usually my application working well, but some time i have got errors and i'm sure that problem is coming from fluent configuration. And I'm sure again i have made some mistake :)

Here is the my SessionFactory Class :

public class NHibernateHelper
{
    private static ISessionFactory sessionFactory;

    /// <summary>
    /// SessionFactory is static because it is expensive to create and is therefore at application scope.
    /// The property exists to provide 'instantiate on first use' behaviour.
    /// </summary>
    private static ISessionFactory SessionFactory
    {
        get
        {
            if (sessionFactory == null)
            {
                sessionFactory = CreateSessionFactory();
            }
            return sessionFactory;
        }
    }


    /// <summary>
    /// CreateSessionFactory
    /// </summary>
    /// <returns></returns>
    private static ISessionFactory CreateSessionFactory()
    {
        IPersistenceConfigurer dbConfigurer = MsSqlConfiguration.MsSql2005
            .ConnectionString("connection string ..")
                            .Cache(c => c
                                .UseQueryCache()
                                .ProviderClass<NoCacheProvider>()
                    ).ShowSql()
                    .CurrentSessionContext<ThreadStaticSessionContext>(); 
                    return Fluently
                            .Configure()
                            .Database(dbConfigurer)
                            .Mappings(mc =>
                            {
                                mc.FluentMappings.Add(typeof(UserMap));
                                mc.FluentMappings.Add(typeof(ApplicationMap));
                                mc.FluentMappings.Add(typeof(SubscriptionsMap));
                            })
                        .BuildSessionFactory();
    }


    public static ISession GetCurrentSession()
    {
        if (!CurrentSessionContext.HasBind(SessionFactory))
        {
            CurrentSessionContext.Bind(SessionFactory.OpenSession());
        }
        return SessionFactory.GetCurrentSession();
    }



    public static void DisposeSession()
    {
        var session = GetCurrentSession();
        session.Close();
        session.Dispose();
    }

    public static void BeginTransaction()
    {
        GetCurrentSession().BeginTransaction();
    }

    public static void CommitTransaction()
    {
        var session = GetCurrentSession();
        if (session.Transaction.IsActive)
            session.Transaction.Commit();
    }

    public static void RollbackTransaction()
    {
        var session = GetCurrentSession();
        if (session.Transaction.IsActive)
            session.Transaction.Rollback();
    }
}

Every thread is calling NHibernateHelper class with this line inside of itself ;

            var myobjectinstance = new ObjectInstance();
            NHibernateHelper.GetCurrentSession().Save( myobjectinstance );

I saw that, when i started server some time it has invoking 300.000 work item for test purpose successfully. But sometime it's giving errors about 2-3 workitem.

The exception is :

[0] = {"An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.\r\n\r\n"}

Inner excetion is :

Object reference not set to an instance of an object.

Inner exception stack trace is :

    at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
    at System.Collections.Generic.Dictionary`2.set_Item(TKey key, TValue value)
    at NHibernate.Impl.SessionFactoryObjectFactory.AddInstance(String uid, String name, ISessionFactory instance, IDictionary`2 properties)
    at NHibernate.Impl.SessionFactoryImpl..ctor(Configuration cfg, IMapping mapping, Settings settings, EventListeners listeners)
    at NHibernate.Cfg.Configuration.BuildSessionFactory()
    at FluentNHibernate.Cfg.FluentConfiguration.BuildSessionFactory() 
    in d:\Builds\FluentNH\src\FluentNHibernate\Cfg\FluentConfiguration.cs:line 93

Any suggestion or help are welcome

+3  A: 

It looks like the CreateSessionFactory method is called multiple times. The sessionFactory static field access is not synchronized in this method which makes it not thread safe:

private static ISessionFactory SessionFactory
{
    get
    {
        if (sessionFactory == null)
        {
            sessionFactory = CreateSessionFactory();
        }
        return sessionFactory;
    }
}

Make sure to always synchronize access to shared resources in multithreaded applications. There's a common used pattern in this situation called singleton.

Darin Dimitrov
Darin thank you for your response, you right but SessionFactory instance too excepsive for every thread. What should i do ? Do you have any suggestion about that ?
fyasar
Yes, synchronize access to it.
Darin Dimitrov
Awesome, i skipped this :) Thank you very much for your feedback Darin.
fyasar
I wrap it in a singleton in the ioc container.
Paco
Hey Paco, can you send me an example about ioc ?
fyasar
I have the same problem, and I use one of the singleton patterns described in the link above. Quite strange. Still looking for a way to: 1st reproduce 2nd fix it.
graffic