2 回答

TA貢獻1784條經驗 獲得超8個贊
鑒于您希望在構造函數中設置備用連接字符串,則表明它是一個已知值。
要解決的問題是如何用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 之前設置該值。

TA貢獻1966條經驗 獲得超4個贊
您應僅在啟動期間注冊 DbContext。
只有您應指定連接字符串。
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnectionString")));
services.AddMvc();
}
如果您使用的是依賴關系注入(來自 MSDN),這一點非常重要:
實體框架上下文應使用作用域生存期將實體框架上下文添加到服務容器。這是在注冊數據庫上下文時通過調用 AddDbContext 方法自動處理的。使用數據庫上下文的服務也應使用作用域內的生存期。
希望這有幫助。
- 2 回答
- 0 關注
- 91 瀏覽
添加回答
舉報