我想从控制器配置连接字符串,但是我找不到任何函数来实现。
我有:
public class tstController : Controller
{
private readonly contextTst _context;
public tstController(contextTst context)
{
_context = context;
_context.Database.**????**
}
}
有可能吗?
非常感谢!
答案 0 :(得分:2)
鉴于您要在构造函数中设置备用连接字符串,这表明它是一个已知值。
要解决的问题是如何使用DI进行此操作。第一个提示是在搭建上下文时生成的代码:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
//#warning To protect potentially sensitive information in your
// connection string, you should move it out of source code.
// See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
optionsBuilder.UseSqlServer("Server=.\\SQLEXPRESS;Database=MyDb;Trusted_Connection=True;");
}
}
这意味着您可以使用默认配置(optionsBuilder.IsConfigured),并在启动时设置该值。而且对施工使用的替代品。
代码将如下所示:
public partial class MyContext : DbContext
{
private readonly string _connectionString;
public MyContext(DbContextOptions<MyContext> options)
: base(options)
{
}
public MyContext(IOptions<DbConnectionInfo> dbConnectionInfo)
{
_connectionString = dbConnectionInfo.Value.MyContext;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(_connectionString);
}
}
}
辅助类如下所示:
public class DbConnectionInfo
{
public string MyContext { get; set; }
}
示例appsettings.json:
"ConnectionStrings": {
"MyContext": "Server=.\\SQLEXPRESS;Database=MyDb;Trusted_Connection=True;"
},
和寄存器都在启动时:
services.Configure<DbConnectionInfo>(settings => configuration.GetSection("ConnectionStrings").Bind(settings));
services.AddScoped<MyContext>();
如果您不想从配置中读取连接字符串,而是根据中间件(例如,每个租户)进行设置,则可以使用相同的方法。 只需在构造上下文之前更新值即可。
更新:
使用依赖注入,您不必自己构造对象,而是将注册的对象/服务作为参数传递。 DI将找出需要以什么顺序创建哪些对象。使用后,DI将以同样的方式处理这些物体。
,该控制器“知道”的上下文中的事实,是因为DI自动将它作为参数。上下文“知道” DbConnectionInfo的事实是因为它已注册到DI。
如果你想改变DbConnectionInfo,那么你需要将它添加以适当的方式。在您的情况下,您可以执行以下操作:
// Added as part of the example
services.AddHttpContextAccessor();
// Replace registration with this line:
services.AddScoped<DbConnectionInfo>();
// Register the DbContext
services.AddScoped<MyContext>();
该类的替代版本为:
public class DbConnectionInfo
{
public string MyContext { get; set; }
// Example injecting IHttpContextAccessor
// On creating this class DI will inject
// the HttpContextAccessor as parameter
public DbConnectionInfo(IHttpContextAccessor httpContextAccessor)
{
// Access the current request
var request = httpContextAccessor.HttpContext.Request;
// Access the current user (if authenticated)
var user = httpContextAccessor.HttpContext.User;
// Now you could get a value from a header, claim,
// querystring or path and use that to set the value:
MyContext = "";
}
}
在DbContext中有一个小的更改,在这种情况下,我们不使用IOptions:
public partial class MyContext : DbContext
{
private readonly string _connectionString;
public MyContext(DbConnectionInfo dbConnectionInfo)
{
_connectionString = dbConnectionInfo.MyContext;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(_connectionString);
}
}
}
现在,每个请求的值都将在创建MyContext之前设置。
答案 1 :(得分:1)
您应该仅在启动期间注册DbContext。
只有您应该指定连接字符串。
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnectionString")));
services.AddMvc();
}
如果您using dependency injection (from MSDN),这是非常重要的:
实体框架上下文应使用作用域生存期将实体框架上下文添加到服务容器。这是 当调用AddDbContext方法时自动处理 注册数据库上下文。使用数据库的服务 上下文还应该使用作用域生存期。
希望这会有所帮助。