ASP.NET MVC多租户使用Autofac和Owin
问题描述:
形势ASP.NET MVC多租户使用Autofac和Owin
分离式数据库,我们必须与SQL Server一起运行一个ASP.NET MVC应用5。我们有一个主数据库,其中包含一个表Tenants
,我们所有的租户都使用连接字符串属性注册到他们自己的个人数据库。
对于认证,我们使用Microsoft Owin
库。
Autofac
我们已经建立autofac这样的:
var builder = new ContainerBuilder();
// Register the controllers
builder.RegisterControllers(typeof(Project.Web.ProjectApplication).Assembly);
// ### Register all persistence objects
// Project main database registration (Peta Poco instance using connectionstring as parameter)
builder.RegisterType<ProjectDatabase>()
.As<ProjectDatabase>()
.WithParameter(new NamedParameter("connectionString", GlobalSettings.ProjectTenantConnectionString))
.InstancePerLifetimeScope();
// Project tenant specific database registration
// ...
// Unit of work
builder.RegisterType<PetaPocoUnitOfWork>()
.As<IDatabaseUnitOfWork>()
.InstancePerRequest();
// ### Register all services
builder.RegisterAssemblyTypes(Assembly.Load("Project.Core"))
.Where(t => t.Name.EndsWith("Service"))
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
// ### Register all repositories
builder.RegisterType<RepositoryFactory>()
.As<IRepositoryFactory>()
.InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(Assembly.Load("Project.Core"))
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
// Register Logging
builder.RegisterType<Logger>().As<ILogger>().InstancePerLifetimeScope();
// Register Automapper
builder.RegisterAssemblyTypes(Assembly.Load("Project.Core")).As<Profile>();
builder.RegisterAssemblyTypes(Assembly.Load("Project.Web")).As<Profile>();
builder.Register(context => new MapperConfiguration(cfg =>
{
foreach (var profile in context.Resolve<IEnumerable<Profile>>())
{
cfg.AddProfile(profile);
}
})).AsSelf().SingleInstance();
builder.Register(c => c.Resolve<MapperConfiguration>().CreateMapper(c.Resolve))
.As<AutoMapper.IMapper>()
.InstancePerLifetimeScope();
// Register Owin
builder.Register(ctx => HttpContext.Current.GetOwinContext()).As<IOwinContext>();
builder.Register(
c => new IdentityUserStore(c.Resolve<IUserService>()))
.AsImplementedInterfaces().InstancePerRequest();
builder.Register(
ctx => ctx.Resolve<IOwinContext>().Authentication)
.As<IAuthenticationManager>().InstancePerRequest();
builder.RegisterType<IdentityUserManager>().AsSelf().InstancePerRequest();
// Build container
var container = builder.Build();
// Tenant container
var tenantIdentifier = new RequestSubdomainStrategy();
var mtc = new MultitenantContainer(tenantIdentifier, container);
// Set autofac as dependency resolver
DependencyResolver.SetResolver(new AutofacDependencyResolver(mtc));
更多细节
使用这个设置中,我们有Autofac一个实例安装到我们的主Tenant
数据库。 然后将其注入我们的PetaPocoUnitOfWork
以进行交易。
这有效,我可以得到租户信息。
但是现在我们需要以下工作,我们不知道从哪里开始。
- 我们如何设置autofac注册租户地图POCO数据库实例注入
PetaPocoUnitOfWork
,以及如何将应用程序现在该怎么解决这个问题?因为我们需要访问2个数据库(主数据库和个人租户数据库),首先需要获取租户连接字符串,然后再对租户数据库执行crud操作。 - 我们的
PetaPocoUnitOfWork
包含数据库的工作方式,我们是否应该为每个租户注册,并使用autofac的解析方法传递数据库,并在每个请求的实例上设置它?
答
实际上,您可以拥有一个使用连接字符串名称和租户上下文的分区管理器[更类似于Microsoft Azure分区管理器]。从这些信息中,它可以解析连接,然后将其传递给上下文。
这将在每个租户的基础上加以解决,然后应用程序使用基于租户连接,即这是在每一项服务的注入,使建立[登录用户的身份]身份可以用来设置EF/Data层中的正确连接对象。这样,它便于松耦合设计,也便于测试和模型。
你可以找到示例代码和这样的实现会是什么样子的小文件从我github repository
恕我直言,这种做法背后的理由,我认为将是每个租户分区将被存储在事实一个数据库[通常是您的主数据库],即使您能够通过Autofac注入这些数据库,也需要获取和使用这些数据库。我没有在这里重现代码,因为它需要一些长的解释来获取代码和解释,这在github中已经得到了关注。
HTH
很高兴地看到,已经3 SO用户要关闭这个问题...如果它能够广泛我应该将它们放置在分离式问题,并在一起或链接...? – Mivaweb