请考虑我已使用.NET Core Web应用程序配置EF:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(...));
我也可以下载一个包来支持例如SQLite:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(...));
我们如何允许用户在应用安装上“选择”提供商?我的意思是 - 例如,在WordPress中,您可以从下拉列表中进行选择。
这在.NET Core中是否可行?我看到的唯一方法是仅重新启动应用程序......
答案 0 :(得分:3)
以下是有关如何实施DbContextFactory
或DbContextProxy<T>
的示例,该public interface IDbContextFactory
{
ApplicationContext Create();
}
public class DbContextFactory() : IDbContextFactory, IDisposable
{
private ApplicationContext context;
private bool disposing;
public DbContextFactory()
{
}
public ApplicationContext Create()
{
if(this.context==null)
{
// Get this value from some configuration
string providerType = ...;
// and the connection string for the database
string connectionString = ...;
var dbContextBuilder = new DbContextOptionsBuilder();
if(providerType == "MSSQL")
{
dbContextBuilder.UseSqlServer(connectionString);
}
else if(providerType == "Sqlite")
{
dbContextBuilder.UseSqlite(connectionString);
}
else
{
throw new InvalidOperationException("Invalid providerType");
}
this.context = new ApplicationContext(dbContextBuilder);
}
return this.context;
}
public void Dispose(){
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing){
if (disposing){
disposing?.Dispose();
}
}
}
或services.AddScopedd<IDbContextFactory, DbContextFactory>();
将创建正确的提供程序并将其返回。
IDbContextProxy<T>
还要确保如上所示实现一次性模式,因此在工厂处置后立即处理上下文,以防止DbContext在内存中保留的时间超过必要时间并尽快释放非托管资源。
最后将工厂注册为作用域,就像上下文本身一样:
DbContextOptionsBuilder
更高级和通用/可扩展的方法是创建一个IDbContextBuilder
类,它使用一些反射来获取正确的构造函数和public class SqlServerDbContextBuilder IDbContextBuilder
{
public bool CanHandle(string providerType) => providerType == "SqlServer";
public T CreateDbContext<T>(connectionString)
{
T context = ... // Create the context here
return context;
}
}
。
也可以创建一个抽象提供者创建的if/else
。
switch
然后,您只需执行
即可选择没有硬编码// Inject "IEnumerable<IDbContextBuilder> builders" via constructor
var providerType = "SqlServer";
var builder = builders.Where(builder => builder.CanHandle(providerType)).First();
var context = builder.CreateDbContext<ApplicationContext>(connectionString);
或XxxDbContextBuilder
块的正确提供商
PBYTE AddPadding(PBYTE Array, int size)
{
if (size % 16 != 0)
{
size += (16 - size % 16);
size = ceil(size / 16) * 16;
}
BYTE* tmp = new BYTE[size];
//the magic should happen here
return tmp;
}
添加新类型的提供程序就像添加依赖项和BYTE in[] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, 0x25 };
PBYTE tmp = AddPadding(in, sizeof(in));
类一样简单。
答案 1 :(得分:0)
我认为您可以使用使用您指定的db上下文的存储库,并且可以将参数传递给上下文构造函数以选择端点。我不确定这一点,但它可能适用于你的情况。
我按照这篇文章讨论了存储库模式,我建议你阅读它:)