【问题标题】:User specific connection string in EntityFramework .net coreEntityFramework .net 核心中的用户特定连接字符串
【发布时间】:2020-07-21 06:54:39
【问题描述】:
我们正在使用 .net 核心和 EntityFramework 开发一个多租户应用程序。将有一个部署的 API 实例,但有多个 DBS(每个用户一个 DB)。那么,将数据库连接字符串更改为每个用户上下文的最佳策略是什么。
【问题讨论】:
标签:
c#
.net
asp.net-mvc
architecture
entity-framework-core
【解决方案1】:
在DbContext 的OnConfiguring 方法中设置连接字符串,通过调用UseSqlServer 或任何您的数据库。在这种方法中,您需要引用一些将提供用户特定连接的服务。为此,IMO,最好的方法是通过DbContext 类注入IHttpContextAccessor,并在OnConfiguring 中使用它来获取HttpContext 和所有注册的服务。您一定不要忘记致电AddHttpContextAccessor 注册IHttpContextAccessor。
示例代码:
//MyContext
public class MyContext : DbContext
{
public MyContext(DbContextOptions options, IHttpContextAccessor httpContextAccessor) : base(options)
{
this.HttpContextAccessor = httpContextAccessor;
}
protected IHttpContextAccessor HttpContextAccessor { get; }
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
var context = this.HttpContextAccessor.HttpContext;
var userService = context.RequestServices<IUserService>();
var user = context.User.Identity.Name;
var connectionString = userService.GetConnectionString(user);
builder.UseSqlServer(connectionString);
base.OnConfiguring(builder);
}
}
//Startup.ConfigureServices
services.AddHttpContextAccessor();
services.AddDbContext<MyContext>();
请注意,IUserService 只是您必须实现的一些服务,它将返回给定用户的连接字符串。
【解决方案2】:
我认为你应该在这个链接中实现类似的东西
https://docs.microsoft.com/en-us/ef/core/miscellaneous/cli/dbcontext-creation
或者喜欢这个例子
using System.Configuration;
using System.Data.SqlClient;
using System.Threading.Tasks;
public interface IDbContextFactory
{
Task<TContext> Create<TContext>(int userId);
}
public class DbContextFactory : IDbContextFactory
{
public DbContextFactory()
{
}
public async Task<TContext> Create<TContext>(int userId)
where TContext: DbContext, new()
{
//TODO: build connectionString using SqlConnectionStringBuilder and replace the values in []
var connectionStringBuilder = new SqlConnectionStringBuilder("Application Name=SSCommitmentService;")
{
DataSource = $"tcp:[dbServer],1433",
InitialCatalog = "[catalog]",
UserID = "[sqlUserid]",
Password = "[sqlPassword]"
};
var options = new DbContextOptionsBuilder<TContext>();
//TODO: configure the DbContextOptions to use the Provider (Sql, MySql, etc)
options.UseSqlServer(connectionStringBuilder.ConnectionString);
//TODO: instantiate the required dbcontext
var dbContext = new TContext(options.Options);
return dbContext;
}
}