-->
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.  [ 10 posts ] 
Author Message
 Post subject: Changing db schema dynamically
PostPosted: Sun Mar 11, 2007 9:59 pm 
Newbie

Joined: Sun Mar 11, 2007 9:46 pm
Posts: 6
I need to be able to allow the users of an ASP.NET web app to select the appropriate database schema at the login screen. Depending on what schema is selected at runtime I will need to use that schema to retrieve the data (but only for that user) for any subsequent data retrievals.

The reason for this is that we keep monthly backups of the data (as the data being stored is MASSIVE), and users may want to do queries on older data.

I have already tried something like this:
GetNHibernateSessionFactory().ConnectionProvider.GetConnection().ChangeDatabase(databaseName);

but that did nothing.

Next i'm thinking of changing the config file for the session, but I believe that would change it for each user.

Any suggestions?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 12, 2007 9:03 pm 
Newbie

Joined: Sun Mar 11, 2007 9:46 pm
Posts: 6
Come on, this should be easy!
It would take me about 5 minutes to do using ADO.NET.

This will be the last straw, if I cannot get this working I will scrap NHibernate and use something that can actually get the job done.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 13, 2007 4:32 am 
Newbie

Joined: Mon Mar 05, 2007 3:50 am
Posts: 6
Are you really using different schemas? Then you also need different mappings, and probably need different SessionFactories using different configurations.

If you just need different connection strings, why not open the ADO-connection yourself and pass it to OpenSession()?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 13, 2007 4:41 am 
Newbie

Joined: Sun Mar 11, 2007 9:46 pm
Posts: 6
The schemas are technically the same, so I do not need different mappings.

Using the method you propose I'm not sure how NHibernate will be able to handle different users using different connection strings.

Either way I will give this a shot and let you know how it goes.

Thanks for the reply!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 13, 2007 4:51 am 
Newbie

Joined: Mon Mar 05, 2007 3:50 am
Posts: 6
Unless you're reconnecting your ISession between http requests there's at most one user (i.e connection string) per ISession. Shouldn't be a problem.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 14, 2007 10:56 am 
Newbie

Joined: Sun Mar 11, 2007 9:46 pm
Posts: 6
Ok I managed to get it working (somewhat). I did it the way you suggested.
However I don't think the way I implemented is very good, maybe you can suggest a better way?

On the login screen I generate the query string based on what DB is selected and then open and store a MySqlConnection in an ASP.NET Session[]

In my HttpModule event (the first event that has access to Sessions), I retrieve the MySqlConnection from the Session[] and use it to call OpenSession(openConnection) .

I really would like an alternate way to do this without using asp.net Sessions...


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 14, 2007 12:51 pm 
Beginner
Beginner

Joined: Wed Mar 14, 2007 12:35 pm
Posts: 24
Oh god... I hope you aren't storing a connection object in session. You'll kill your app as soon as you put any kind of load on it.

We had a similar situation. We ended building the connection string per request in an http module once we knew the users database. I don't really like this implementation myself, but it was necessary.

Code:
// build session factory on app start.. should only be built once
static ISessionFactory factory;

// ex authenticate request
string connectionStringPrototype = ConfigurationManager.AppSettings["connectionStringPrototype"];
string connectionString = String.Format(connectionStringPrototype, "users database");
HttpContext.Current.Items["NH_SESSION"] = factory.OpenSession(new SqlConnection(connectionString));

// end request
ISession session = (ISession)HttpContext.Current.Items["NH_SESSION"];
session.Flush();
session.Close();


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 14, 2007 10:54 pm 
Newbie

Joined: Sun Mar 11, 2007 9:46 pm
Posts: 6
Yeah, I was storing the connection object in a session :(.

I was just wondering with the code example above, how did you store/retrieve "users database".

I am now putting the connection string into the session[] instead of the connection object, I'd imagine you would've done something similar?

The last thing that I need to take care of now is opening/closing the SqlConnection.
This should be openened for each user only once ever, so how do I persist that?
And when/where should I close it? calling session.close() will not close the database connection.

Thanks for the help!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 16, 2007 8:52 am 
Beginner
Beginner

Joined: Wed Mar 14, 2007 12:35 pm
Posts: 24
IF you simply must keep some sort of reference to a DB connection object, use it on a PER request basis (ie HttpContext.Current.Items).

My best recommendation is to use a custom (or alter the existing one) ConnectionProvider (NHibernate.Connection.ConnectionProvider) that way you can truly control the connections being created and closing them specifically when NHibernate is saying it is done with them. The abstract class is super simple to use.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 20, 2007 9:41 pm 
Newbie

Joined: Sun Mar 11, 2007 9:46 pm
Posts: 6
I'll have a look at the NHibernate.Connection.ConnectionProvider, might prove to be useful in the future.

I discovered an even easier way to change the database dynamically.
Here is an example of what I do now:


Code:
        public void ChangeDatabase(string databaseName)
        {
            ISession session = ThreadSession;

            if (session != null && session.IsOpen)
            {
                session.Connection.ChangeDatabase(databaseName);
            }

            ThreadSession = session;
        }

Where session is ISession.
This seems to do the job, and makes the code look much cleaner.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 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.