我有一个业务ASP.NET MVC5应用程序,每个客户都有自己的数据库。我想将EF6和Ninject用于DI。对于登录,我使用的是ASP.NET Identity。
对于每个用户,都有一个UserClaim,其中指定了数据库的名称:
依此类推...这意味着这是一个带有“共享”数据库的Web应用程序,用于用户身份验证,另一方面,每个客户都有自己的数据库-所有数据库都位于同一数据库服务器(MS SQL Server)上。
用户需要登录,登录后他应该从他的个人数据库(在UserClaim-Table中指定)接收数据。
对于Ninject,我认为我必须要做这样的事情
private void AddBindings() {
kernel.Bind<EFDBContext>().ToMethod(c => new EFDBContext("db_name"));
}
但是如何将UserClaim纳入绑定中?(我不想使用会话,因为会话可能会丢失)。
绑定之后需要什么步骤?
例如,在AccountRepository中,EFDBContext期望使用“ db_name”>,但是我该如何到达那里呢?
public class AccountRepository : IAccountRepository {
private EFDBContext context = new EFDBContext("db_name");
}
最后,我可以在此类内部更改连接字符串?
public class EFDBContext : DbContext {
public EFDBContext(string db_name) : base("EFDBContext") {
}
}
@Hooman Bahreini回答后更新
NinjectDependencieResolver.cs
private void AddBindings() {
kernel.Bind<ICustomerRepository>().To<CustomerRepository>().WithConstructorArgument("http_current_context", HttpContext.Current);
}
CustomerRepository.cs
public class CustomerRepository : ICustomerRepository {
private CustomerDBContext context;
public CustomerRepository(HttpContext httpContext) {
string db_name = "";
var claimValue = ((ClaimsPrincipal)HttpContext.Current.User).Claims.FirstOrDefault(c => c.Type == "db_name");
if(claimValue != null) {
db_name = claimValue.Value.ToString();
}
context = new CustomerDBContext(db_name);
}
public IEnumerable<Test> Tests {
get { return context.Test; }
}
}
数据库上下文文件
public class CustomerDBContext : DbContext {
public CustomerDBContext(string db_name) : base("CustomerDBContext") {
string temp_connection = Database.Connection.ConnectionString.Replace(";Initial Catalog=;", ";Initial Catalog=" + db_name + ";");
Database.Connection.ConnectionString = temp_connection;
}
public DbSet<Test> Test { get; set; }
}
您可以从访问用户声明HttpContext
:
var claimValue = ((ClaimsPrincipal)HttpContext.Current.User)
.Claims
.FirstOrDefault(c => c.Type == "db_name");
对于您的ninject代码,您可以创建以下扩展方法HttpContext
:
public static HttpcontextExtensions
{
public static string GetDbName(this HttpContext context)
{
return ((ClaimsPrincipal)context.Current.User)
.Claims
.FirstOrDefault(c => c.Type == "db_name");
}
}
并使用以下ninject绑定:
kernel.Bind<ICustomerRepository>()
.To<CustomerRepository>()
.WithConstructorArgument("db_name", HttpContext.GetDbName());
有关在ninject中访问的更多信息,请参阅此文档HttpContext
。
在您的示例中,CustomerRepository
依赖于HttpContext
,这不是一个好的设计。CustomerRepository
需要一个db-name,这就是应该在构造函数中传递的名称。与此相关的是尼古拉的IoC第四定律
被解析的类的每个构造函数除了接受一组自己的依赖关系之外,都不应具有任何实现。
举个例子,您HttpContext
的测试项目中没有任何内容,这使单元测试CustomerRepository
变得复杂。
PS我不知道您的设计,但也许从db-name中获取HttpContext
不是一个理想的解决方案...用户可能会注销或清除其浏览器历史记录,并且您将失去db-name。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句