简体   繁体   English

使用 EF Core 在运行时确定正在使用哪个数据库提供程序

[英]Determine at runtime which db provider is being used, with EF Core

In our ASP.NET Core and EF Core system, we use different databases for different parts of the system.在我们的 ASP.NET Core 和 EF Core 系统中,我们为系统的不同部分使用不同的数据库。 I need to be able to tell, at runtime, which db provider is being used, because some stuff needs to take this into account.我需要能够在运行时知道正在使用哪个 db 提供程序,因为有些东西需要考虑到这一点。

During startup, there is this for SQL Server:在启动过程中,SQL Server 有这个:

  services.AddDbContext<MyContext>(
    options => options.UseSqlServer(config.GetConnectionString("DefaultConnection"))
  );

or this for SQLite:或者这对于 SQLite:

  services.AddDbContext<MyContext>(
    options => options.UseSqlite(config.GetConnectionString("DefaultConnection"))
  );

The point being that the knowledge of which database is being used, is contained within the system, somewhere.关键是正在使用哪个数据库的知识包含在系统中的某个地方。

At some arbitrary point in the system, how can I determine which database I'm using?在系统中的某个任意点,我如何确定我使用的是哪个数据库? I have access to the MyContext .我可以访问MyContext Is there something in there that can reveal this info?有什么东西可以揭示这些信息吗?

I use in my project 3 database providers.我在我的项目中使用了 3 个数据库提供程序。

  • Npgsql.EntityFrameworkCore.PostgreSQL Npgsql.EntityFrameworkCore.PostgreSQL
  • Microsoft.EntityFrameworkCore.SqlServer Microsoft.EntityFrameworkCore.SqlServer
  • Pomelo.EntityFrameworkCore.MySql Pomelo.EntityFrameworkCore.MySql

Not used in my project.在我的项目中没有使用。 Update .更新 June 17, 2020. I noticed that the Oracle Provider has an extensión method IsOracle. 2020 年 6 月 17 日。我注意到 Oracle Provider 有一个扩展方法 IsOracle。

Include in your client project, any of those references, can be added from Nuget Package manager or CLI.在您的客户端项目中,可以从 Nuget 包管理器或 CLI 添加任何这些引用。

The references contains the following extension methods.参考资料包含以下扩展方法。

Boolean isPostgreSQL = context.Database.IsNpgsql();
Boolean isSqlServer = context.Database.IsSqlServer();
Boolean isMySql = context.Database.IsMySql();
Boolean isOracle= context.Database.IsOracle();

Example 1示例 1

public static EntityTypeBuilder<TEntity> ToTable<TEntity>(this EntityTypeBuilder<TEntity> builder, string schema, DatabaseFacade database) where  TEntity : class
{
    switch(database)
    {
        case DatabaseFacade db when db.IsMySql():
            builder.ToTable($"{schema}.{typeof(TEntity).Name}");
            break;

        case DatabaseFacade db when db.IsSqlServer() | db.IsNpgsql():
            builder.ToTable(typeof(TEntity).Name, schema);
            break;
        default:
            throw new NotImplementedException("Unknown database provider.");
    }
    return builder;
}

Example 2示例 2

private static string GetEffectiveConstraintName(string name, DatabaseFacade database)
{
    return database switch
    {
        DatabaseFacade db when db.IsSqlServer() => name,
        DatabaseFacade db when db.IsNpgsql() => name.Length < DataAccessConstants.PostgreSqlIdentifierMaxLength ? name : name.Substring(0, DataAccessConstants.PostgreSqlIdentifierMaxLength),
        DatabaseFacade db when db.IsMySql() => name.Length < DataAccessConstants.MySqlIdentifierMaxLength ? name : name.Substring(0, DataAccessConstants.MySqlIdentifierMaxLength),
        _ => throw new NotImplementedException("Unknown database provider")
    };
}

Anywhere in the system, where you have access to the MyContext , do this:在系统中的任何地方,您可以访问MyContext ,请执行以下操作:

context.Database.GetDbConnection().GetType().Name

For example, it is SqliteConnection for SQLite, or SqlServerConnection for SQL Server, etc.比如,SQLite 是SqliteConnection ,SQL Server 是SqlServerConnection等。

However I'm not sure if you'll need to dispose the connection afterwards!但是,我不确定您之后是否需要处理连接!

I'm not sure if there is a public way of doing it, but you can look at context.Database.DatabaseCreator (you'll have to use reflection to get to DatabaseCreator), but by looking at the type, you can tell what kind of connection it is.我不确定是否有这样做的公共方式,但是您可以查看 context.Database.DatabaseCreator(您必须使用反射才能访问 DatabaseCreator),但是通过查看类型,您可以知道是什么它是一种联系。 For example, with SQL, you'll get SqlServerDatabaseCreator.例如,使用 SQL,您将获得 SqlServerDatabaseCreator。

EDIT: Yeah, looking at the code, I don't think there is any other way to tell besides what I mentioned above.编辑:是的,看看代码,除了我上面提到的,我认为没有其他方法可以说明。 The UseSqlServer method doesn't set any flags anywhere or anything like that. UseSqlServer 方法不会在任何地方或类似的地方设置任何标志。 It's just a factory.这只是一个工厂。

对于 EF 核心 2:

dbContext.Database.ProviderName

One point where you could start is the DbContextOptions<T> , which is what the AddDbContext<T> method does, which you can see here .您可以开始的一点是DbContextOptions<T> ,这是AddDbContext<T>方法所做的,您可以在这里看到。

Which in turn gets injected into the DbContext.这反过来又被注入到 DbContext 中。

You could try to request DbContextOptions or DbContextOptions<MyContext> in your service too and then interate/inspect the Extensions dictionary.您也可以尝试在您的服务中请求DbContextOptionsDbContextOptions<MyContext> ,然后交互/检查扩展字典。

SqliteOptionsExtension is Sqlite one, you can see it registered here and here . SqliteOptionsExtension是 Sqlite 之一,您可以在此处此处看到它已注册。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM