2010-03-09 10 views
5

Ho creato un'applicazione multithread su IIS (ASP.NET MVC). Quando il server di threading ha iniziato, crea 10 thread e sta eseguendo workitems nei thread.Fluent Nibernazione errore di configurazione nell'applicazione multithreading

Di solito la mia applicazione funziona bene, ma qualche volta ho degli errori e sono sicuro che il problema derivi da una configurazione fluente. E sono sicuro che ancora una volta ho fatto un errore :)

Qui è la mia classe SessionFactory:

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

Ogni filo chiama classe NHibernateHelper con questa linea dentro di sé;

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

Ho visto che, quando ho avviato il server un po 'di tempo, ha richiamato con successo 300.000 elementi di lavoro a scopo di test. Ma a volte sta dando errori circa 2-3 workitem.

L'eccezione è:

excetion interiore è:

Object reference not set to an instance of an object. 

dello stack eccezione interna è:

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 

Qualsiasi suggerimento o aiuto sono i benvenuti

risposta

7

Sembra che il metodo CreateSessionFactory sia chiamato più volte. Il sessionFactory accesso campo statico non è sincronizzato in questo metodo, che lo rende non thread-safe:

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

Assicurarsi sempre di sincronizzare l'accesso alle risorse condivise nelle applicazioni multithreaded. C'è un modello usato comune in questa situazione chiamata singleton.

+0

Darin grazie per la risposta, hai ragione, ma l'istanza di SessionFactory è troppo esagerata per ogni thread. Cosa dovrei fare ? Hai qualche suggerimento a riguardo? – fyasar

+0

Sì, sincronizza l'accesso ad esso. –

+0

Impressionante, l'ho saltato :) Grazie mille per il tuo feedback Darin. – fyasar