【问题标题】:ASP.NET MVC Multi Tenant with seperated databases using Autofac and Owin具有使用 Autofac 和 Owin 的独立数据库的 ASP.NET MVC 多租户
【发布时间】:2017-07-16 17:09:02
【问题描述】:

情况

我们有一个与 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().Inst‌​ancePerRequest();

// 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 以提交事务。

这行得通,我可以得到租户信息。

但现在我们需要以下工作,我们不知道从哪里开始。

  1. 我们如何设置 autofac 来注册租户 peta poco 数据库实例以注入 PetaPocoUnitOfWork 以及应用程序现在如何解决这个问题?因为我们需要访问 2 个数据库(主数据库和个人租户数据库),首先获取租户连接字符串,然后对租户数据库进行 crud 操作。
  2. 我们的 PetaPocoUnitOfWork 包含要使用的数据库,我们是否应该也为每个租户注册它并使用 autofac 的解析方法传递数据库并在每个请求的实例上设置它?

【问题讨论】:

  • 很高兴看到已经有 3 个 SO 用户想要关闭这个问题......如果它太宽泛,我应该将它们放在单独的问题中并将它们链接在一起还是......?

标签: asp.net asp.net-mvc dependency-injection autofac multi-tenant


【解决方案1】:

您实际上可以有一个分片管理器 [更类似于 Microsoft Azure 分片管理器],它采用连接字符串名称和租户上下文。根据这些信息,它可以解析连接,然后将其传递给 Context。

这将在每个租户的基础上解决,然后应用程序与基于租户的连接一起工作,即这被注入到每个服务中,以便可以使用建立的身份 [登录用户身份] 来设置EF / 数据层中的正确连接对象。这样,它有利于松耦合设计,也易于测试和模拟。

您可以从我的github repository 中找到示例代码和关于这种实现的外观的少量文档

恕我直言,我建议这种方法背后的基本原理是,每个租户的分区将存储在数据库 [通常是您的主数据库] 中,即使您有能力也需要获取和使用- 如何通过 Autofac 注入这些。我没有在这里复制代码,因为这里需要很长的解释才能得到代码和解释,这在github中得到了照顾。

HTH

【讨论】:

    猜你喜欢
    • 2021-04-03
    • 1970-01-01
    • 2015-12-16
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多