我知道你们中的一些人会看着我,并因我的愚蠢而翻白眼,但是我们所有人都必须从某个地方开始!我有一个场景,其中有一个数据库服务器,但是多个数据库共享相同的架构。目前,我正在为每个数据库重写代码,而且情况一团糟,所以我试图清除它。我在这里变得很困惑,所以我正在寻找一些大师的建议。我是这里的初学者,尝试做一些我觉得很高级的事情,所以请放轻松。我将仅使用两个数据库保留示例,但实际上有10多个数据库都是相同的,因此我经常需要在它们之间进行切换。我的目标是在我要保存或访问记录并让一件事控制所有记录的情况下,尽量消除所有这些1、2、3、4、9、10等东西。
我为数据库上下文创建了一个基类
public partial class opkDataBaseContext : DbContext
{
private DbContextOptions<opkData1Context> options1;
private DbContextOptions<opkData2Context> options2;
public opkDataBaseContext()
{
}
public opkDataBaseContext(DbContextOptions<opkDataBaseContext> options)
: base(options)
{
}
public opkDataBaseContext(DbContextOptions<opkData1Context> options)
{
this.options1 = options;
}
public opkDataBaseContext(DbContextOptions<opkData2Context> options)
{
this.options2 = options;
}
public virtual DbSet<OrgUnits> OrgUnits { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
...
}
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
public void CreateNewOrganization(CreateCompleteOrgViewModel model)
{
var nameParameter = new SqlParameter("@TopLevelOrgName", model.Name);
var codeParameter = new SqlParameter("@Code", model.Code);
var DbNameParameter = new SqlParameter("@DBName", model.DbCatalog);
var debugParameter = new SqlParameter("@debug", "0");
var firstNameParameter = new SqlParameter("@FirstName", model.FirstName);
var lastNameParameter = new SqlParameter("@LastName", model.LastName);
var userNameParameter = new SqlParameter("@Username", model.UserName);
this.Database.ExecuteSqlRaw("CreateRootOrg @TopLevelOrgName, @Code, @DBName, @debug, @FirstName, @LastName, @Username",
nameParameter, codeParameter, DbNameParameter, debugParameter, firstNameParameter, lastNameParameter, userNameParameter);
}
这是我的Startup.cs
public void ConfigureServices(IServiceCollection services)
{
if (_env.IsProduction())
{
var opkCoreConnection = Configuration.GetConnectionString("opkCoreDatabase");
services.AddDbContext<opkCoreContext>(options => options.UseSqlServer(opkCoreConnection));
var opkData1Connection = Configuration.GetConnectionString("opkData1Database");
services.AddDbContext<opkData1Context>(options => options.UseSqlServer(opkData1Connection));
var opkData2Connection = Configuration.GetConnectionString("opkData2Database");
services.AddDbContext<opkData2Context>(options => options.UseSqlServer(opkData2Connection));
var opkDataLocalBaseConnection = Configuration.GetConnectionString("opkDataBaseDatabase");
services.AddDbContext<opkDataBaseContext>(options => options.UseSqlServer(opkDataLocalBaseConnection));
然后对于每个数据库,我都有一个:
public partial class opkData1Context : opkDataBaseContext
{
public opkData1Context()
{
}
public opkData1Context(DbContextOptions<opkData1Context> options)
: base(options)
{
}
我当前的错误是:
“验证服务描述符'ServiceType:Models.DataModels.opkDataBaseContext时发生错误:范围实现类型:Models.DataModels.opkDataBaseContext':无法激活类型'Models.DataModels.opkDataBaseContext'。以下构造函数不明确:\ r \ nVoid .ctor(Microsoft.EntityFrameworkCore.DbContextOptions'1 [Models.DataModels.opkDataBaseContext])\ r \ nVoid .ctor(Microsoft.EntityFrameworkCore.DbContextOptions'1 [Models.opkData1Context])“} System.Exception {System.InvalidOperationException}
我整天都在混乱。首先,我什至走了正确的道路,还是只是一个愚蠢的想法?第二,知道我要去哪里了吗?谢谢!
答案 0 :(得分:1)
我有一个场景,其中有一个数据库服务器,但是多个数据库共享相同的模式
在软件即服务(SaaS)应用程序中,这是非常普遍的,甚至是最佳实践。
虽然这并不明显,但事实证明它很简单。您只需要一些在运行时选择连接字符串的方法,可能是基于config和HttpContext中的某些内容(例如用户的身份,路径,主机标头等)的组合。然后像这样为DI配置DbContext:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddDbContext<MyDbContext>((sp, opt) =>
{
var httpContext = sp.GetRequiredService<IHttpContextAccessor>();
var config = sp.GetRequiredService<IConfiguration>();
string connectionString = GetConnectionStringFromHttpContext(httpContext, config);
opt.UseSqlServer(connectionString, o => o.UseRelationalNulls());
});
services.AddControllers();
}
其中GetConnectionStringFromHttpContext
是一个自定义方法,可基于配置和HttpContext从中构建连接字符串。
答案 1 :(得分:0)
您可以看看EF Core 5 preview 1中引入的功能(请注意,最新功能是预览5),该功能可以在已初始化的上下文中更改连接或连接字符串