Nhibernate中session的状态与session.connection.state状态的差别的解释

在项目中用到了nhibernate,但是需要判断数据连接的状态,在NHIbernate的文档中找了半天,英文的中文的都看了一遍,都没找到相关的说明 。后来在Hibernate的论坛上才找到了一些说明。摘录如下:


 Post subject: Check if database is available

Posted: Tue Sep 18, 2007 10:33 am 

 

 

 

Beginner

 

 


Joined: Tue May 30, 2006 10:55 am
Posts: 21

 


Is there a best practice for testing a database connection? Because I am using more than one database I hope there is such a functionality inside of NHibernate.
 
Hibernate version: 1.2.0

Name and version of the database you are using: MS SQL, Informix

 

 

 

 

 

Top


  
 
 

 

 

 


jlockwood

 

 

 Post subject:

Posted: Tue Sep 18, 2007 10:46 am 

 

 

 

Regular

 

 


Joined: Fri Jan 20, 2006 7:45 pm
Posts: 97
Location: San Antonio, TX

 


To support multiple databases you would need a config file (or programattically, config methods) for each database concerned. You would also need to create a session factory for each database.
 
As far as testing for each connection, you could wrap the configuration of each session factory in a try/catch. You would catch the config error raised if the database isn't found (I'm not sure what it is off hand) and then could dump the exception and log the error using log4net (only if the failed connection is not a terminal condition).
 
I'm not sure what it would mean to you if you couldn't connect to one of the two databases, so I can't say what the behavior should be if a connection failed. In any case, you could have a central SessionManager that can hand out sessions from both factories. This could be a thread-safe singleton. I haven't tested shared transaction contexts across 2 databases, but I imagine that there's some support for enlisting transactions from sessions on the other database (I'm only guessing).
 
Billy McCafferty has a decent example of using multiple databases with NHibernate here:
 http://www.codeproject.com/aspnet/NHibe ... ctices.asp

I wrote a short blog a while bag that shows how to enlist transactions into an ADO Command, but that was for doing work outside the cache but within the same transaction context:
 http://www.lostechies.com/blogs/joshua_ ... ction.aspx

Does that help?

_________________
Dum spiro, spero
-------------------------------
Rate my post if it helps...

 

 


 

 

Top


  
 
 

 

 

 


torrud

 

 

 Post subject:

Posted: Tue Sep 18, 2007 11:10 am 

 

 

 

Beginner

 

 


Joined: Tue May 30, 2006 10:55 am
Posts: 21

 


Thanks for your reply. I will read the articles soon.

But at the moment I am standing a few steps earlier. All I want to do with the databases works for the moment but I get in trouble when a database is not accessible maybe during a network error or a mistyped password etc.
 
So I have to check whether a connection to a database is possible. At the moment I catch the exceptions from the session factory but I hoped that there is a better way without throwing/catching exceptions to test the configuration. I can not give the exception message to the user because it is to much technical. And so I get in trouble how to determine what goes wrong.
 
Is there no smarter way?

 

 

 

 

 

Top


  
 
 

 

 

 


jlockwood

 

 

 Post subject:

Posted: Tue Sep 18, 2007 11:44 am 

 

 

 

Regular

 

 


Joined: Fri Jan 20, 2006 7:45 pm
Posts: 97
Location: San Antonio, TX

 


For helping in debugging, you could use log4net to intercept NHibernate logs. That would help with trouble shooting.
 
For instance, if you had a malformed password you would get an ADOException forces by the database itself. Unfortunately, thet won't log in you NHibernate logs all you'll see is something like this:
 NHibernate.Connection.DriverConnectionProvider [(null)] - Obtaining IDbConnection from Driver
 
...and then the log stops.

I'm using Oracle, so even if the database can't be found I'll still get an Oracle exception back as an ADOException (TNS not resolved). From NHibernate's perspective it will look the same:
 DEBUG NHibernate.Connection.DriverConnectionProvider [(null)] - Obtaining IDbConnection from Driver
 
For failed connections and authentication you won't see an exception until you try to begin a new transaction or flush a transient object to the database. That being said, you could force a check of the connection with something like this:
 
Code:

session.Connection.Open();

 

If the database can't be found or authentication is bad and ADOException would be raised when forcing the Open().
 
So, beging transaction or a forced open would raise the exception and allow you to do a check before continuing execution.
 
Does that do it for you?
_________________
Dum spiro, spero
-------------------------------
Rate my post if it helps...

 

 


 

 

Top


  
 
 

 

 

 


torrud

 

 

 Post subject:

Posted: Wed Sep 19, 2007 8:45 am 

 

 

 

Beginner

 

 


Joined: Tue May 30, 2006 10:55 am
Posts: 21

 


I am followed your advice and wrote this code:


Code:

internal bool IsDatabaseAvailable
{
  get
    {
      bool available = false;
      ISession session = null;

      try
      {
        session = factory.OpenSession(); //gets a new session from the session factory
        available = session.IsConnected;
      }
      catch(Exception ex)
      {
        //add entry to application log   
      }
      finally
      {
        if (null != session)
          session.Close();
      }

      return available;
  }
}

 

But I get now one problem. If I use a wrong username session.IsConnected returns true but the session.Connection property returns an ADOException as it should. Why the IsConnected property returns "true" and not "false"? Maybe a bug?
 
Any suggestions?

 

 


 

 

Top


  
 
 

 

 

 


jlockwood

 

 

 Post subject:

Posted: Wed Sep 19, 2007 10:38 am 

 

 

 

Regular

 

 


Joined: Fri Jan 20, 2006 7:45 pm
Posts: 97
Location: San Antonio, TX

 

 

torrud wrote:

But I get now one problem. If I use a wrong username session.IsConnected returns true but the session.Connection property returns an ADOException as it should. Why the IsConnected property returns "true" and not "false"? Maybe a bug?

Any suggestions?

 
session.IsConnected is different. You can think of it as IsConnectable, since you can have "Connected" and "Disconnected" sessions. If you call session.Diconnect(), you can no longer persist data to the database. session.Reconnect() will allow you to persist to the DB again. This does not mean that you have an open connection, it just means that you are capable of opening a connection if you were to begin a transaction. If you look at the NHibernate log file, I believe that you wouldn't see the line that says that the connection was opened. This is because the connection isn't needed yet.
 
Calling session.Connection.Open() would force the connection to open and thus raise your exception.
 
Make sense?
_________________
Dum spiro, spero
-------------------------------
Rate my post if it helps...

 

 


 

 

Top


  
 
 

 

 

 


torrud

 

 

 Post subject:

Posted: Wed Sep 19, 2007 12:13 pm 

 

 

 

Beginner

 

 


Joined: Tue May 30, 2006 10:55 am
Posts: 21

 

 

jlockwood wrote:

session.IsConnected is different. You can think of it as IsConnectable, since you can have "Connected" and "Disconnected" sessions. If you call session.Diconnect(), you can no longer persist data to the database. session.Reconnect() will allow you to persist to the DB again. This does not mean that you have an open connection, it just means that you are capable of opening a connection if you were to begin a transaction. If you look at the NHibernate log file, I believe that you wouldn't see the line that says that the connection was opened. This is because the connection isn't needed yet.

Calling session.Connection.Open() would force the connection to open and thus raise your exception.

Make sense?
 

Yes, it does. But one additional question. There is a property called session.IsOpen. This property is still "true" like session.IsConnected but can I have a disconnected session which is open? I thought one of these both properties should give me the right information but they do not. For the moment I have changed my code and now it works.
 

Code:

.
.
.
try
{
  session = factory.OpenSession();
 
  //if something is wrong the following statement throws an ADOException
  available = (ConnectionState.Open == session.Connection.State);
}
.
.
.

 

 

 


 

 

Top


  
 
 

 

 

 


jlockwood

 

 

 Post subject:

Posted: Wed Sep 19, 2007 1:44 pm 

 

 

 

Regular

 

 


Joined: Fri Jan 20, 2006 7:45 pm
Posts: 97
Location: San Antonio, TX

 


Yes...
If you have an open session and call:

Code:

session.Disconnect();

session.IsOpen would equal true
session.IsConnected would equal false

If you have an open session and call:

Code:

session.Close();
 
session.IsOpen would equal false
session.IsConnected would equal false

If you try to save using a disconnected session, you get a HibernateException.

I think you might be able to load objects from a disconnected session's cache using session.Load(entityId, typeof(EntityType)), but I haven't tested this so I don't know for certain.
 
In a nutshell,
session.IsOpen indicates if session is open regardless of connection state
session.IsConnected indicates if a session is "Connected" and thus can establish new AdoConnections
_________________
Dum spiro, spero
-------------------------------
Rate my post if it helps...

 

 


 

 

Top


  
 
 

 

 

 

 

Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending 

 


 原来,还是要以session.connection.state为准来判断连接的状态。

 

 

 

 

using NHibernate; using NHibernate.Cfg; using System; namespace Nebula.EAP.Core.Scenario.Dao.Session { /// /// 读写分离 /// public class ReadWriteSessionManager : IDisposable { /// /// 读操作工厂 Lazy /// private static readonly Lazy _readSessionFactory = new Lazy(() => BuildSessionFactory("EAP_ORA_READ")); /// /// 写操作工厂 Lazy /// private static readonly Lazy _writeSessionFactory = new Lazy(() => BuildSessionFactory("EAP_ORA_WRITE")); private static readonly IConnectionProvider _connectionProvider; static ReadWriteSessionManager() { _connectionProvider = new ConnectionProvider(); } /// /// 读操作 /// /// public ISession OpenReadSession() => _readSessionFactory.Value.OpenSession(); /// /// 写操作 /// /// public ISession OpenWriteSession() => _writeSessionFactory.Value.OpenSession(); /// /// 读写操作 /// /// public ReadWriteSession OpenReadWriteSession() => new ReadWriteSession(OpenReadSession(), OpenWriteSession()); /// /// 创建session工厂 /// /// /// /// private static ISessionFactory BuildSessionFactory(string key) //读写工厂各执行一次 { var config = new Configuration(); config.Configure(); config.Properties["connection.connection_string"] = _connectionProvider.GetConnectionString(key); return config.BuildSessionFactory(); } public void Dispose() { } } public class ReadWriteSession : IDisposable { public ISession readSession { get; } public ISession writeSession { get; } public ReadWriteSession(ISession readSession, ISession writeSession) { this.readSession = readSession; this.writeSession = writeSession; } public void Dispose() { readSession?.Dispose(); writeSession?.Dispose(); } } } 这是我读写分离的功能 , 帮我添加一个功能 , 如果 写操作 写到 只读库 , 则报错
06-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值