New Posts New Posts RSS Feed: WinRT, Code First - changing connection string on server side
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

WinRT, Code First - changing connection string on server side

 Post Reply Post Reply
Author
zbig View Drop Down
Newbie
Newbie
Avatar

Joined: 13-Oct-2012
Posts: 28
Post Options Post Options   Quote zbig Quote  Post ReplyReply Direct Link To This Post Topic: WinRT, Code First - changing connection string on server side
    Posted: 17-Jul-2013 at 1:55pm
Hi,

WinRT, Code First, DevForce 2012 7.2.

I am implementing quite common (I hope) SaaS scenario, where logged in user should connect to its own database (connection string for specific user is stored in central db). And here is my question - how to change connection string on the server side according to logged-in user? In other words, how to intercept each server side EntityManager call (query or save) to be able to read appropriate connection string from DB and then execute such calls (queries or save changes) with this new connection.

When I was working with 'old' Silverlight WCF application, I was able to achieve this by writing code in MyService.svc.cs class constructor and using HttpContext.Current.User.Identity to identify currently logged in user.

How to achieve this with DevForce?
I have no 'Entry point' in EntityManager class on server side where (in constructor or in OnInitialize() method) I could query central DB for new connection string and then change it for next DB operations.
I can't use HttpContext.Current.User.Identity too, until I'm using custom LoginManager.

I have tried to apply this description:

http://drc.ideablade.com/devforce-2012/bin/view/Documentation/persistent-connections

but there is no GetServerSessionInfo() method in SessionBundle.CurrentSessionBundle class (DevForce 7.2, Ultimate).

Are there any recommendation for achieving above scenario?
Thanks in advance.
       
Back to Top
sbelini View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 13-Aug-2010
Location: Oakland
Posts: 786
Post Options Post Options   Quote sbelini Quote  Post ReplyReply Direct Link To This Post Posted: 17-Jul-2013 at 3:21pm
Hi zbig,

You could try using DataSourceExtensions, i.e. where the username would be the data source extension.

You can find out more at http://drc.ideablade.com/devforce-2012/bin/view/Documentation/create-entitymanager-datasource-extension and check this sample at http://drc.ideablade.com/devforce-2012/bin/view/Documentation/code-sample-data-source-extensions.
Back to Top
zbig View Drop Down
Newbie
Newbie
Avatar

Joined: 13-Oct-2012
Posts: 28
Post Options Post Options   Quote zbig Quote  Post ReplyReply Direct Link To This Post Posted: 18-Jul-2013 at 2:07pm
Thank you, but it solves the problem only partially.
This solution assumes, that all connections will be stored in web.config, while in my case they will be stored in DB.

I know that connections in configuration can be changed dynamically, but still there is no place to do such change before executing each query and before saving each changes on server side.

Where is the best place (if any) to intercept each EntityManager communication with SQL server?
Back to Top
smi-mark View Drop Down
DevForce MVP
DevForce MVP
Avatar

Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
Post Options Post Options   Quote smi-mark Quote  Post ReplyReply Direct Link To This Post Posted: 18-Jul-2013 at 2:32pm
You can make your own custom key resolver on the server and intercept this call:

http://drc.ideablade.com/devforce-2012/bin/view/Documentation/code-sample-custom-datasourcekeyresolver
Back to Top
zbig View Drop Down
Newbie
Newbie
Avatar

Joined: 13-Oct-2012
Posts: 28
Post Options Post Options   Quote zbig Quote  Post ReplyReply Direct Link To This Post Posted: 20-Jul-2013 at 1:37pm
Hi

It works fine and it solves my scenario, thank you!

However in my case one user (some kind of supervisor) can have access to many databases (identical db schema, database can be chosen on client side, no relogin required). For that reason it would be very usefull if EntityManager had a method to change datasource without necessity of relogin - kind of myEntityManager.ChangeDataSource(string userName, string dataSourceName) with possibility of intercept this call on server side.
Back to Top
smi-mark View Drop Down
DevForce MVP
DevForce MVP
Avatar

Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
Post Options Post Options   Quote smi-mark Quote  Post ReplyReply Direct Link To This Post Posted: 21-Jul-2013 at 9:48am
Hmm.. But then you have the issue where you might have things in the cache of an EM, so you would be clearing it out anyways, it seems like you'd be better off creating a new EntityManager.

You should be able to make this seamless to the user, as they will already be authenticated, you will just be specifying a new context.

Perhaps you could have the datasource name be the username by default such as "MyUserName" but if they pick another database it could be something like "MyUsername_Database1" then in your code you can parse the username and then confirm they can have access to Database1
Back to Top
zbig View Drop Down
Newbie
Newbie
Avatar

Joined: 13-Oct-2012
Posts: 28
Post Options Post Options   Quote zbig Quote  Post ReplyReply Direct Link To This Post Posted: 27-Jul-2013 at 12:42pm
Thanks a lot for advices.

After several attempts I think, I am much more familiar with this mechanism.

I have noticed, that the only way to execute GetKey(...) method of RccDataSourceKeyResolver class (on server side) is to create a new instance of EntityManager (on client side) and then execute query, save or make login. GetKey() method is executed only once for one instance (logical).

The problem with this approach is a container (I'm using Unity on client side and my MyEntityManager is registered as an instance - singleton). When I have to instantiate new EntityManager each time when I want to change DB, I have to slightly break architecture and I have to expose my container as public static to be able to register new EntityManager instance somewhere inside AccountService (App.Container.RegisterInstance<MyEntityManager>(newMyEntityManager)). But anyway, problem solved.

I have only one short question regarding LoginManager - what is the main purpose of passing EntityManager to Login(...) method?
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down