2012-02-02 75 views
0
private ISessionFactory GetSessionFactory(string sessionFactoryConfigPath) 

    { 
     GetFullSessionFactoryFor(sessionFactoryConfigPath); 
     while (!sessionFactoryReady) Thread.Sleep(1000); 
     return (ISessionFactory)sessionFactories[sessionFactoryConfigPath]; 
} 


private void GetFullSessionFactory(string sessionFactoryConfigPath) 
    {  
    ThreadPool.QueueUserWorkItem(state => 
     { 
      ISessionFactory sessionFactory=null; 
      FluentConfiguration fluentConfiguration = fluentConfiguration.ExposeConfiguration(c => c.SetProperty("sessionfactoryname","somevalue")) 
             .Mappings(m => 
             { 
              m.FluentMappings 
               .AddFromAssembly(Assembly.Load("nameofassembly")) 
               .Conventions.Add(DefaultLazy.Always(), 
                    OptimisticLock.Is(x => x.All()), 
                    DynamicUpdate.AlwaysTrue(), 
                    DynamicInsert.AlwaysFalse(), 
                    DefaultCascade.None() 
                   ) 
               .Conventions.AddFromAssemblyOf<"SomeConvention">(); 
             } 
               ); 

     sessionFactory = fluentConfiguration.BuildSessionFactory(); 

      }); 
} 

我創建的主線程(這裏沒有顯示),並在第二個線程全會話工廠minisession工廠。 問題是,當它命中buildsessionfactory代碼永遠不會返回。我做對了嗎?多線程與功能NHibernate

public class NHibernateBaseDAO<T> 
{ 
    public NHibernateBaseDAO(string sessionFactoryConfigPath, int sessionId) 
    { 


     SessionFactoryConfigPath = sessionFactoryConfigPath; 
     SessionId = sessionId; 
    public bool Save(T entity) 
    { 
     bool saveSuccessful = true; 
     try 
     { 
      NHibernateSession.Save(entity); 
     } 
     catch (NHibernate.HibernateException) 
     { 
      saveSuccessful = false; 
     } 
     return saveSuccessful; 
    } 

    public bool SaveOrUpdate(T entity) 
    { 
     bool saveSuccessful = true; 
     try 
     { 
      NHibernateSession.SaveOrUpdate(entity); 
     } 
     catch (NHibernate.HibernateException) 
     { 
      saveSuccessful = false; 
     } 
     return saveSuccessful; 
    } 

    public void Delete(T entity) 
    { 
     NHibernateSession.Delete(entity); 

    } 

    public void CommitChanges() 
    { 
     if (NHibernateSessionManager.Instance.HasOpenTransactionOn(SessionFactoryConfigPath, this.SessionId)) 
     { 
      NHibernateSessionManager.Instance.GetSessionFrom(SessionFactoryConfigPath, this.SessionId).Flush(); 
      NHibernateSessionManager.Instance.CommitTransactionOn(SessionFactoryConfigPath, this.SessionId); 
     } 
     else 
     { 
      NHibernateSessionManager.Instance.GetSessionFrom(SessionFactoryConfigPath, this.SessionId).Flush(); 
     } 
    } 

    public void BeginTransaction() 
    { 
     NHibernateSessionManager.Instance.BeginTransactionOn(SessionFactoryConfigPath, this.SessionId); 
    } 

    public void RollbackTransaction() 
    { 
     NHibernateSessionManager.Instance.RollbackTransactionOn(SessionFactoryConfigPath, this.SessionId); 
    } 

    public bool IsDirty() 
    { 
     return NHibernateSession.IsDirty(); 
    } 

    public IQueryable<T> Query() { 
     return (IQueryable<T>)NHibernateSession.Query<T>(); 

    } 
    protected ISession NHibernateSession 
    { 
     get 
     { 
      return NHibernateSessionManager.Instance.GetSessionFrom(SessionFactoryConfigPath, this.SessionId); 
     } 
    } 


    protected readonly string SessionFactoryConfigPath; 
    protected int SessionId; 

    protected System.Data.IDbConnection DbConnection 
    { 
     get { return NHibernateSessionManager.Instance.GetDbConnection(SessionFactoryConfigPath, this.SessionId); } 
    } 

    /// <summary> 
    /// Return a list of object arrays. use this for general queries 
    /// </summary> 
    public System.Collections.IEnumerable GetSqlQuery(string queryString, IList<Criterion> criterion, Type returnType) 
    { 
     queryString += CriteriaToSql(criterion); 

     return NHibernateSession.CreateQuery(queryString).Enumerable(); 
    } 

    protected ICriteria AddCriteria(IList<Criterion> criterion) 
    { 
     ICriteria criteria = NHibernateSession.CreateCriteria(persistentType); 

     foreach (Criterion criterium in criterion) 
     { 
      switch (criterium.Comparison) 
      { 
       case SqlComparison.StartsWith: 
        criteria.Add(Restrictions.InsensitiveLike(criterium.Property, criterium.Value1.ToString(), MatchMode.Start)); 
        break; 

       case SqlComparison.Contains: 
        criteria.Add(Restrictions.InsensitiveLike(criterium.Property, criterium.Value1.ToString(), MatchMode.Anywhere)); 
        break; 

       case SqlComparison.Equals: 
        criteria.Add(Restrictions.Eq(criterium.Property, criterium.Value1)); 
        break; 

       case SqlComparison.Between: 
        criteria.Add(Restrictions.Between(criterium.Property, criterium.Value1, criterium.Value2)); 
        break; 
       case SqlComparison.MoreThan: 
        criteria.Add(Restrictions.Gt(criterium.Property, criterium.Value1)); 
        break; 
       case SqlComparison.LessThan: 
        criteria.Add(Restrictions.Lt(criterium.Property, criterium.Value2)); 
        break; 
       case SqlComparison.InList: 
        criteria.Add(Restrictions.In(criterium.Property, (System.Collections.IList)criterium.Value1)); 
        break; 

      } 
     } 
     return criteria; 
    } 
    protected string CriteriaToSql(IList<Criterion> criterion) 
    { 

    } 
    /// <summary> 
    /// Get delimiter for data, defaults to ' unless specifed for data type 
    /// </summary> 
    protected string[] GetDelimiter(object value) 
    { 

} 
public class Criterion 
{ 
    public Criterion(string property, SqlComparison comparison, object value1) 
    { 
     Property = property; 
     Comparison = comparison; 
     Value1 = value1; 
    } 
    public Criterion(string property, SqlComparison comparison, object value1, object value2) 
    { 
     Property = property; 
     Comparison = comparison; 
     Value1 = value1; 
     Value2 = value2; 
    } 
    public Criterion(string property, SqlComparison comparison, object value1, bool not) 
    { 
     Property = property; 
     Comparison = comparison; 
     Value1 = value1; 
     Not = not; 
    } 
    public Criterion(string property, SqlComparison comparison, object value1, object value2, bool not) 
    { 
     Property = property; 
     Comparison = comparison; 
     Value1 = value1; 
     Value2 = value2; 
     Not = not; 
    } 
    public string Property { get; set; } 
    public bool Not { get; set; } 
    public SqlComparison Comparison { get; set; } 
    public object Value1 { get; set; } 
    public object Value2 { get; set; } 
} 
public enum SqlComparison { StartsWith, Contains, Equals, Between, MoreThan, LessThan, InList } 
} 

請最後一個問題。我使用泛型類來訪問sessionfactory,所以我不能明確地訪問minisession。我如何在完全會話不可用的情況下僅基於某些實體訪問minisession,並在完全會話工廠可用時訪問。

回答

1

你永遠sessionfactoryready設置爲true

更新:一個更完整的例子。

void Main() 
{ 
    Database.InitRealFactoryAsync("<sessionFactoryConfigPath>"); 

    var minifactory = Database.GetMiniFactory("<sessionFactoryConfigPath>"); 

    // Do some stuff with minifactory 

    var realsessionfactory = Database.SessionFactory; 

    // Do stuff with real factory 
} 

static class Database 
{ 
    private static ISessionFactory sessionFactory; 

    public void InitRealFactoryAsync(string sessionFactoryConfigPath) 
    { 
     ThreadPool.QueueUserWorkItem(state => 
     { 
      sessionFactory = Fluently.Configure() 
       .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.Load("nameofassembly")) 
        .Conventions.Add(DefaultLazy.Always(), 
         OptimisticLock.Is(x => x.All()), 
         DynamicUpdate.AlwaysTrue(), 
         DynamicInsert.AlwaysFalse(), 
         DefaultCascade.None()) 
        .Conventions.AddFromAssemblyOf<FoxproDateConvention>()) 
       .BuildSessionFactory(); 
     }); 
    } 

    public ISessionFactory GetMiniFactory(string sessionFactoryConfigPath) 
    { 
     var assembly = Assembly.Load("nameofassembly"); 
     return Fluently.Configure() 
      .Mappings(m => m.FluentMappings.Add(assembly.GetTypes().Where(Filter).ToArray()) 
       .Conventions.Add(DefaultLazy.Always(), 
        OptimisticLock.Is(x => x.All()), 
        DynamicUpdate.AlwaysTrue(), 
        DynamicInsert.AlwaysFalse(), 
        DefaultCascade.None()) 
       .Conventions.AddFromAssemblyOf<FoxproDateConvention>()) 
       .BuildSessionFactory(); 
    } 

    public static ISessionFactory SessionFactory 
    { 
     get { 
      while (sessionFactory == null) Thread.Sleep(1000); 
      return sessionFactory; 
     } 
    } 
} 

UpdateUpdate:

void Main() 
{ 
    Database.InitRealFactoryAsync("<sessionFactoryConfigPath>"); 
    Database.InitMiniFactory("<sessionFactoryConfigPath>"); 

    using (var session = Database.GetSession(true)) 
    { 
     // Do some stuff where minifactory is enough 
    } 

    using (var session = Database.GetSession()) 
    { 
     // Do stuff with real factory 
    } 
    ... 
} 

// class Database 
public ISession GetSession() 
{ 
    return GetSession(false); 
} 

public ISession GetSession(bool miniFactoryIsEnough) 
{ 
    if (realSessionfactory != null) 
     return realSessionfactory.OpenSession(); 
    if (miniFactoryIsEnough) 
     return miniSessionfactory.OpenSession(); 
    else 
    { 
     while (realSessionFactory == null) Thread.Sleep(1000); 
     return realSessionfactory.OpenSession(); 
    } 
} 

更新:

你需要指定要在會話中使用類型爲 「僅基於某些實體訪問minisession」:

public ISession GetSession(Type persistentType) 
{ 
    if (fullSessionfactory != null) 
     return realSessionfactory.OpenSession(); 
    if (miniFactory.GetClassMetadata(persistentType) != null) 
     return miniSessionfactory.OpenSession(); 
    else 
    { 
     // minifactory doesnt contain the type needed, wait for full factory 
     while (fullSessionFactory == null) Thread.Sleep(1000); 
     return fullSessionfactory.OpenSession(); 
    } 
} 

一些額外的建議

catch (NHibernate.HibernateException)

FlushMode應是Flushmode.Commitpublic void CommitChanges()可以寫成

var session = NHibernateSession; 
if (session.Transaction.IsActiv) 
{ 
    session.Transaction.Commit(); 
} 

刪除了整個sessionId的東西,因爲它似乎沒有提供任何價值。保持會話而不是sessionId

+0

我們是否需要鎖定線程進行同步? – arjun 2012-02-02 15:21:24

+0

有人可以幫助我爲什麼線程在builsessionfactory realsessionfactory之後永遠不會返回 – arjun 2012-02-03 06:18:45

+0

我不相信buildsessionfactory從不返回,它很可能是GetSessionfactory()。 Plz在一個簡單的控制檯應用程序中嘗試我的代碼,以瞭解它是如何完成的 – Firo 2012-02-03 06:59:55