gpt4 book ai didi

c# - 在 ASP.NET MVC 3 Web App + Ninject + EF 中为不同的用户设置不同的连接字符串

转载 作者:行者123 更新时间:2023-11-30 12:30:15 25 4
gpt4 key购买 nike

我正在尝试弄清楚如何根据每个 Web 请求设置不同的连接字符串。

这是我的场景:

  • 一个基于 asp.net mvc 3 + ninject + Entity Framework 的单一网络应用
  • 一个实体模型
  • 具有相同模型的三个物理上不同的数据库

到目前为止,我尝试做的是通过重写基本 Controller 的 OnActionExecuting 方法(每个 Controller 都继承自自定义基础)来设置默认 Controller 工厂(传递正确的连接字符串),但是如果我尝试与两个应该同时访问不同数据库的不同用户一起访问是行不通的。似乎第一个用户设置了他的连接字符串,第二个用户选择了已经设置的连接字符串,而没有设置新的默认 Controller 。

这是一些代码...

// 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 实现限制为单个请求。我说的对不对?

最佳答案

解决方案是直接注入(inject)连接字符串,而是注入(inject)某种IConnectionFactory并移动开关(Request.Url.Host) 工厂实现的代码。这简化了您的注册并消除了实现 ControllerBase 的需要。

您的问题类似于this question我刚刚回答的。

更新

实现这个的方法在一定程度上取决于您的应用程序、它的设计和要求,但是您可以在应用程序的核心层中定义以下 IConnectionFactory:

public interface IConnectionFactory
{
SqlConnection OpenConnection();
}

由于数据库的选择特定于 ASP.NET 的使用,因此您必须在 MVC 项目中定义此接口(interface)的实现。它可能如下所示:

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;
}
}

您可以通过以下方式注册:

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

您的 SqlUsersRepository(以及所有其他服务)现在可以依赖于 IConnectionFactory 而不是 string

这样,您的服务就不必知道如何为它们自己创建连接,并且您已将其抽象化。这使得以后重构和更改代码变得更加容易。

您甚至可能想更进一步,将 DbContextIDbContextFactory 注入(inject)您的存储库。

关于c# - 在 ASP.NET MVC 3 Web App + Ninject + EF 中为不同的用户设置不同的连接字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16665721/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com