grokky
grokky

Reputation: 9295

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. I need to be able to tell, at runtime, which db provider is being used, because some stuff needs to take this into account.

During startup, there is this for SQL Server:

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

or this for 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. Is there something in there that can reveal this info?

Upvotes: 22

Views: 8281

Answers (5)

Joma
Joma

Reputation: 3869

I use in my project 3 database providers.

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

Not used in my project. Update. June 17, 2020. I noticed that the Oracle Provider has an extensión method IsOracle.

Include in your client project, any of those references, can be added from Nuget Package manager or 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

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

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")
    };
}

Upvotes: 22

alignnc
alignnc

Reputation: 131

For EF Core 2:

dbContext.Database.ProviderName

Upvotes: 5

grokky
grokky

Reputation: 9295

Anywhere in the system, where you have access to the MyContext, do this:

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

For example, it is SqliteConnection for SQLite, or SqlServerConnection for SQL Server, etc.

However I'm not sure if you'll need to dispose the connection afterwards!

Upvotes: 13

Tseng
Tseng

Reputation: 64307

One point where you could start is the DbContextOptions<T>, which is what the AddDbContext<T> method does, which you can see here.

Which in turn gets injected into the DbContext.

You could try to request DbContextOptions or DbContextOptions<MyContext> in your service too and then interate/inspect the Extensions dictionary.

SqliteOptionsExtension is Sqlite one, you can see it registered here and here.

Upvotes: 1

SledgeHammer
SledgeHammer

Reputation: 7736

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. For example, with SQL, you'll get 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. It's just a factory.

Upvotes: 2

Related Questions