Учитывая тот факт, что вы хотите установить альтернативную строку соединения в конструкторе, можно предположить, что это известное значение.
Нужно решить, как это сделать с 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 автоматически добавляет его в качестве параметра.Тот факт, что контекст «знает» 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.