c# - Setting up different connection strings for different user in an ASP.NET MVC 3 Web App + Ninject + EF -
i'm trying figure out how set different connection string upon each web request.
this scenario:
- one single webapp based on asp.net mvc 3 + ninject + entity framework
- one single entity model
- three phisically different databases same model
what i've tried far set default controller factory (passing right connection string) overriding onactionexecuting method of base controller (every controller inherited custom base) if try access 2 different users should access different databases @ same time doesn't work. seems first user set connection string , second 1 pick 1 it's set without setting new default controller.
here's code...
// base controller public class basecontroller : controller { protected override void onactionexecuting(actionexecutingcontext filtercontext) { var database = string.empty; switch (request.url.host) { case "aaa.domain.local": database = "aaa"; break; case "bbb.domain.local": database = "bbb"; break; case "ccc.domain.local": database = "ccc"; break; } controllerbuilder.current.setcontrollerfactory(new ninjectcontrollerfactory(webconfigurationmanager.connectionstrings[database].connectionstring)); } } // ninject controller factory public class ninjectcontrollerfactory : defaultcontrollerfactory { private ikernel _kernel; public ninjectcontrollerfactory() { } public ninjectcontrollerfactory(string connectionstring) { _kernel = new standardkernel(new abcservices(connectionstring)); } protected override icontroller getcontrollerinstance(system.web.routing.requestcontext requestcontext, type controllertype) { if (controllertype == null) return null; return (icontroller)_kernel.get(controllertype); } private class abcservices : ninjectmodule { private string _connectionstring; public abcservices(string connectionstring) { _connectionstring = connectionstring; } public override void load() { bind<iusersrepository>(). to<sqlusersrepository>(). inrequestscope(). withconstructorargument("connectionstring", _connectionstring); } } }
as can see i'm using .inrequestscope() limit ninject implementation single request. right or not?
the solution not inject connection string directly, inject iconnectionfactory
of sort , move switch (request.url.host)
code factory implementation. simplifies registration , removes need implementing controllerbase
.
your problem similar this question answered.
update
the way implement depends bit on application, design , requirements, instance define following iconnectionfactory
in core layer of application:
public interface iconnectionfactory { sqlconnection openconnection(); }
since selection of database specific use of asp.net, have define implementation of interface in mvc project. might follows:
public class aspnethostdatabaseconnectionfactory : iconnectionfactory { public sqlconnection openconnection() { string connstr = getconnectionstring(); var connection = new sqlconnection(connstr); connection.open(); return connection; } // old code onactionexecuting method. private static string getconnectionstring() { var database = string.empty; switch (httpcontext.current.request.url.host) { case "aaa.domain.local": database = "aaa"; break; case "bbb.domain.local": database = "bbb"; break; case "ccc.domain.local": database = "ccc"; break; } return webconfigurationmanager .connectionstrings[database].connectionstring; } }
you can register follows:
kernel.bind<iconnectionfactory>() .to<aspnethostdatabaseconnectionfactory>();
your sqlusersrepository
(and other services) can depend on iconnectionfactory
instead of string
.
this way services don't know have know how create connection them selves , you've abstracted away. makes refactoring , changing code later on easier.
you might want go step further , and inject dbcontext
or idbcontextfactory
repositories.
Comments
Post a Comment