These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 
Author Message
 Post subject: Check if database is available
PostPosted: Tue Sep 18, 2007 10:33 am 
Beginner
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
 Profile  
 
 Post subject:
PostPosted: Tue Sep 18, 2007 10:46 am 
Regular
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
 Profile  
 
 Post subject:
PostPosted: Tue Sep 18, 2007 11:10 am 
Beginner
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
 Profile  
 
 Post subject:
PostPosted: Tue Sep 18, 2007 11:44 am 
Regular
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
 Profile  
 
 Post subject:
PostPosted: Wed Sep 19, 2007 8:45 am 
Beginner
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
 Profile  
 
 Post subject:
PostPosted: Wed Sep 19, 2007 10:38 am 
Regular
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
 Profile  
 
 Post subject:
PostPosted: Wed Sep 19, 2007 12:13 pm 
Beginner
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
 Profile  
 
 Post subject:
PostPosted: Wed Sep 19, 2007 1:44 pm 
Regular
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
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.