在ASP.NET MVC 3 Web应用程序+ Ninject + EF设置为不同的用户不同的连接字符串 [英] Setting up different connection strings for different user in an ASP.NET MVC 3 Web App + Ninject + EF

查看:158
本文介绍了在ASP.NET MVC 3 Web应用程序+ Ninject + EF设置为不同的用户不同的连接字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找出如何建立在每个Web请求一个不同的连接字符串。

I'm trying to figure out how to set up a different connection string upon each web request.

这是我的方案:


  • 基于asp.net的MVC一个单一的Web应用3 + ninject +实体框架

  • 一个单一的实体模型

  • 三phisically不同的数据库使用相同型号

我已经试过到目前为止做的是重写基控制器(每个控制器从一个自定义的基本继承)的OnActionExecuting方法来设置默认的控制器工厂(传递正确的连接字符串),但如果我尝试与应在同一时间它不起作用访问不同数据库两个不同的用户访问。看来,第一个用户设置了连接字符串,第二个选择它已设置不设置新的默认控制器之一。

What I've tried to do so far is to set the default controller factory (passing the right connection string) by overriding the OnActionExecuting method of the base controller (every controller is inherited from a custom base) but if I try to access with two different users that should access different databases at the same time it doesn't work. It seems that the first user set his connection string and the second one pick the one it's already set without setting a new default controller.

下面是一些code ...

Here's some 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);
        }
    }
 }

正如你可以看到我使用.InRequestScope()来限制ninject落实到单个请求。我说的对不?

As you can see I'm using .InRequestScope() to limit the ninject implementation to the single request. Am I right or not?

推荐答案

解决方案是的的直接注入一个连接字符串,而是注入了 IConnectionFactory 某种与移动开关(Request.Url.Host) code到工厂实现。这简化了您的注册,并删除不需要实施 ControllerBase

The solution is to NOT inject a connection string directly, but inject an IConnectionFactory of some sort and move the switch (Request.Url.Host) code to the factory implementation. This simplifies your registration and removes the need for implementing a ControllerBase.

您的问题是类似<一个href=\"http://stackoverflow.com/questions/16652839/configuring-structuremap-to-generate-and-remember-a-constructor-param-literal\">this 的问题,我刚才已经回答。

Your problem is similar to this question that I just answered.

更新

要实现这一点的方法取决于你的应用程序,其设计和它的要求了一点,但你可以例如定义应用程序的核心层以下 IConnectionFactory

The way to implement this depends a bit on your application, its design and its requirements, but you could for instance define the following IConnectionFactory in the core layer of your application:

public interface IConnectionFactory
{
    SqlConnection OpenConnection();
}

由于数据库的选择是特定于使用ASP.NET,你会在你的MVC项目来定义这个接口的实现。它看起来如下:

Since the selection of the database is specific to the use of ASP.NET, you will have to define an implementation of this interface in your MVC project. It might look as follows:

public class AspNetHostDatabaseConnectionFactory 
    : IConnectionFactory
{
    public SqlConnection OpenConnection()
    {
        string connStr = GetConnectionString();

        var connection = new SqlConnection(connStr);

        connection.Open();

        return connection;
    }

    // This is the old code from your 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 it as follows:

kernel.Bind<IConnectionFactory>()
    .To<AspNetHostDatabaseConnectionFactory>();

SqlUsersRepository (和所有其他服务)现在可以靠的 IConnectionFactory 代替字符串

Your SqlUsersRepository (and all other services) can now depend on the IConnectionFactory instead of a string.

这样,你的服务不知道要知道如何为他们创造自我的连接,你已经抽象送人。这使得重构,稍后更容易改变你的code。

This way your services don't know have to know how to create a connection for them selves and you've abstracted this away. This makes refactoring and changing your code later on easier.

您可能甚至想走得更远一步,并注入的DbContext IDbContextFactory 到您的资料库。

You might even want to go a step further and and inject a DbContext or IDbContextFactory into your repositories.

这篇关于在ASP.NET MVC 3 Web应用程序+ Ninject + EF设置为不同的用户不同的连接字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆