ASP Core 3.1多变的DB上下文。

问题描述 投票:2回答:2

我有一个问题,关于如何为多个客户设置一个项目。我们目前开发的是一个ASP Core应用程序。所有的客户端都使用相同的数据库结构,所以他们的数据库是相同的,只是填充的用户不同,... 我们目前使用一个publish,在IIS上设置了两个测试网站,每个publish都有一个不同的JSON配置文件,包含DB上下文(在Startp.cs处读出)。

我们这里的问题是,如果我们有多个客户端,就必须多次复制我们的publish来维护IIS的多个网站。我们没有找到一种方法,只用一个publish,并定义配置文件,以依赖连接客户端的URLport来使用。我们尝试了ASP Core下的租户教程,但在用户管理处失败了。

谁能告诉我,对于这种需要在IIS下发布一个共享的websitepublish,为每个客户端(URLport)提供不同的DB上下文,用户认证(我们使用了Identity)的webproject,什么是最好的解决方案。我们已经尝试了几个星期,但都没有成功。我们的主要问题是,DB上下文是在主机建立之前在Startup.cs中创建的,所以我们没有任何来自请求的URL,也不能在应用程序启动时创建一个特定的DB上下文。这意味着,我们无法填充UserStore,也无法让登录工作。我们知道我们可以建立一个包含所有用户和域的主表,但我们真的希望避免这种方法,因为我们不确定,如果网站将运行在同一台服务器上,或者如果一个客户可能使用他自己的公司内部服务器。

EDIT:我需要说得更具体一些,因为我犯了一个小错误。数据库是相同的。所以我实际上不需要不同的上下文类,而只是需要不同的连接字符串。但它们是在Startup.cs的AddDbContext函数中设置的。

EDIT2:我现在尝试了几个解决方案,我总是在Identity上失败。在Startup过程中没有直接创建DbContext的时候,好像就不行了,而且还崩溃了。

EDIT3: 由于我目前失败了,这里有一些来自我们项目的代码片段。

在我们的Startup.csConfigureServices(IServiceCollection services)

  • 我们从一个配置文件中加载我们的DB设置。
    IConfigurationSection DbSection = Configuration.GetSection("Database");
  • 我们正在添加DB上下文
    services.AddDbContext<MyDbContext>(options => options.UseSqlServer(MyDbContext.createConnectionString(DbSection), b => b.MigrationsAssembly("MyNamespace.DB").EnableRetryOnFailure()));
  • 并设置身份认证
    services.AddScoped<Microsoft.AspNetCore.Identity.SignInManager<MyUser>, MySignInManager>();
    services.AddScoped<Microsoft.AspNetCore.Identity.IUserStore<MyUser>, MyUserStore>();
    services.AddScoped<Microsoft.AspNetCore.Identity.UserManager<MyUser>, Services.LogIn.MyUserManager>();

    services.AddIdentity<MyUser, MyRole>()
                    .AddUserManager<MyUserManager>()
                    .AddUserStore<MyUserStore>()
                    .AddRoleStore<MyRoleStore>()
                    .AddDefaultTokenProviders();
  • 我们正在增加授权
    services.AddAuthorization(options =>
        { options.DefaultPolicy = new AuthorizationPolicyBuilder()
                      .RequireAuthenticatedUser()
                      .Build();
        });

在我们的Startup.csConfigure(...) - 我们设置了UseAuthorization

    app.UseAuthentication();
    app.UseAuthorization();

在我们的MyDbContext类中,我们正在创建连接字符串。

     public static string createConnectionString(IConfigurationSection configurationSection)
            {
                return @"server=" + configurationSection.GetSection("Server").Value +
                       ";database=" + configurationSection.GetSection("Database").Value +
                       ";persist security info=True;user id=" + configurationSection.GetSection("User").Value +
                       ";password=" + configurationSection.GetSection("Password").Value + ";multipleactiveresultsets=True;";

            }

所以基本上我们所要实现的,就是为不同的urls建立不同的连接。比方说,我们有2个cients。

clientone.mysite.com:123 -> database_clientone
clienttwo.mysite.com:456 -> database_clienttwo

这是不可能的,因为我们在创建DbContext时没有域名。但是我们要求每个数据库都存储自己的登录凭证,而不是使用一个主表来存储每个现有用户数据库的所有登录信息......。

而且Identity似乎也不能在这种情况下工作。

c# asp.net-core iis-7
2个回答
0
投票

如果你是在Core的DI中通过注册你的DB上下文 AddDbContext 调用,你可以利用它的过载,提供给你访问 IServiceProvider:

public void ConfigureServices(IServiceCollection services)
       {
           services
               .AddEntityFrameworkSqlServer()
               .AddDbContext<MyContext>((serviceProvider, options) =>
               {
                    var connectionString = serviceProvider.GetService // get your service 
                        // which can determine needed connection string based on your logic
                         .GetConnectionString();
                    options.UseSqlServer(connectionString);
               });
       }

也是 此处 类似的东西是实现与Autofac。


0
投票

你可以有多个appsettings.json文件,并根据客户端加载相应的json文件。在上述情况下,你仍然会在Startup.cs中创建DbContext。

public class ConfigurationService : IConfigurationService
    {


        public IConfiguration GetConfiguration()
        {
            var env = GetCurrentClient();//You can also set environment variable for client

            CurrentDirectory = CurrentDirectory ?? Directory.GetCurrentDirectory();
            return new ConfigurationBuilder()
                .SetBasePath(CurrentDirectory)
                  .AddJsonFile("appsettings.json", optional: false, reloadOnChange: false)
                 .AddJsonFile($"appsettings.{env}.json", optional: true, reloadOnChange: false)

                .AddEnvironmentVariables()
                .Build();



        }
    }

0
投票

而不是使用AddDbContext,尝试使用注入DBContext lazily.Add一个类DataContext将实现DBContext。

public class DataContext : DbContext
    {

        public DataContext(IConfigurationService configService)
            : base(GetOptions( GetConnectionString())
        {
            this.ChangeTracker.LazyLoadingEnabled = true;
        }


        private static DbContextOptions GetOptions(string connectionString)
        {

            return SqlServerDbContextOptionsExtensions.UseSqlServer(new DbContextOptionsBuilder(), connectionString).Options;
        }


      public static string GetConnectionString()
        {
           //Your logic to read connection string by host
           // This method will be called while resolving your repository
        }

    }

在你的 的调用,而不是使用Startup.cs删除AddDbContext()调用,而使用

  public void ConfigureServices(IServiceCollection serviceCollection)
        {
            serviceCollection.AddScoped<DbContext, YourDBContext>();
//likewise Addscope for your repositories and other services
//Code to build your host
}

DI DbContext在你的控制器的构造函数或服务的构造函数中。

由于你的DBContext现在被懒惰地加载,你将能够根据你的主机决定连接字符串。

希望这对你有用!


0
投票

我试图通过web.config创建一个环境变量,并在我们的应用程序中读取它。但我找不到一种方法,如何在IIS7中设置多个网站,使用相同的publishfile-文件夹,但不同的web.config文件。这也不行,至少我不知道如何实现这个目标......

© www.soinside.com 2019 - 2024. All rights reserved.