【问题标题】:Dynamic database connectionstring based on Identity Claims基于身份声明的动态数据库连接字符串
【发布时间】:2018-05-05 12:59:46
【问题描述】:

我正在向我的网络应用程序添加一些“租赁”。
我的 Web 应用程序使用 2 个数据库

  • 身份数据库
  • 一个租户特定的数据库(所有相同的架构)

应用程序是第二次使用 一个静态 连接字符串构建的 数据库。

我使用静态连接字符串的正常工作的 AppointmentsControllers:

public class AppointmentsController : Controller
{
    private appDbContext _context;

    public AppointmentsController()
    {
        _context = new appDbContext();
    }

    protected override void Dispose(bool disposing)
    {
        _context.Dispose();
    }

    // Index
    public ViewResult Index()
    {
        var query = from c in _context.Appointments
                    orderby c.RegistrationDate
                    select c;
        //etc...
    }
}

为了添加一些多租户,我更改了 DbContext 部分,以便我可以修改数据库连接。 这部分工作正常,它允许我更改数据库名称:

public class appDbContext : DbContext
{
    public DbSet<Appointments> Appointments { get; set; }

    public appDbContext(string database)
        : base(@"Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=" + database + ";Integrated Security=True")
    {
    }
}

从这里我迷路了。从我的 AppointmentsController 构造函数中连接正确的数据库似乎可能,如下所示:

public class AppointmentsController : Controller
{
    private appDbContext _context;

    public AppointmentsController()
    {
        _context = new appDbContext("DbName");
    }

但我无法从身份中检索我的声明并将其从此构造函数传递给构造函数,如下所示:

public class AppointmentsController : Controller
{
    private appDbContext _context;

    public AppointmentsController()
    {
        var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
        var currentUser = manager.FindById(User.Identity.GetUserId());
        _context = new appDbContext(currentUser.DBName);
    }           

所以我完成工作的最佳方法是这样,但我认为它不是很干净/顺利:

public class AppointmentsController : Controller
{
    private appDbContext _context;

    public AppointmentsController()
    {
        _context = new appDbContext("");
    }

    protected override void Dispose(bool disposing)
    {
        _context.Dispose();
    }

    private string GetCurrentUserDatabaseName()
    {
        var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
        var currentUser = manager.FindById(User.Identity.GetUserId());

        return currentUser.DBName;
    }

    // Index
    public ViewResult Index()
    {
        _context = new appDbContext(GetCurrentUserDatabaseName());

        var query = from c in _context.Appointments
                    orderby c.RegistrationDate
                    select c;
     //etc
    }
}

我觉得我很接近了,但我该如何改进这段代码?

【问题讨论】:

    标签: c# asp.net-mvc connection-string claims-based-identity


    【解决方案1】:

    Web.Config中添加两个连接字符串:

      <connectionStrings>
        <add name="DefaultConnection" connectionString=Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=DefaultDataBase;Integrated Security=True" providerName="System.Data.SqlClient" />     
      </connectionStrings>
    

    然后

        public class ApplicationDbContext : DbContext //change DbContext name appDbContext by ApplicationDbContext
            {
                public DbSet<Appointments> Appointments { get; set; }
    
                public ApplicationDbContext(database=""): base("name=DefaultConnection")
                {
              //And/Or you can do this programmatically.
              if(!string.IsNullOrWhiteSpace(database)
                 {
                   this.Database.Connection.ConnectionString = @"Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=" + database + ";Integrated Security=True";
     //OR Database.Connection.ChangeDatabase(database);
                 }
                // More Stuff.....
                }
            }
    

    使用:

    public class AppointmentsController : Controller
    {
        private ApplicationDbContext _context;
    
        public AppointmentsController()
        {
            _context = new ApplicationDbContext("DataBasConnection");
        }
    }
    

    当你需要 DefultDatabase 时

    public class AppointmentsController : Controller
    {
        private ApplicationDbContext _context;
    
        public AppointmentsController()
        {
            _context = new ApplicationDbContext();
        }
    }
    

    【讨论】:

    • 租户连接字符串需要声明依赖。例如; “用户 a”有一个声明“数据库 A”,“用户 b”有一个声明“数据库 B”。所以我必须在运行时的某个地方传递声明?
    • 我有同样的 Szenario。我认为提供 Connectionstring 作为用户声明,但不确定它是否被允许且足够安全以在令牌中传输密码?
    • @Mustafa 是允许的。我的建议是在声明中加密您的数据库名称或使用格式化字符串。
    猜你喜欢
    • 1970-01-01
    • 2011-11-06
    • 2013-03-08
    • 2011-07-02
    • 2014-02-17
    • 2014-02-28
    • 2016-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多