Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 391
grokky Avatar asked Nov 15 '16 23:11

grokky


4 Answers

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.

  • Oracle.EntityFrameworkCore Oracle.EntityFrameworkCore 3.19.0-beta1

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")
    };
}
like image 184
Joma Avatar answered Oct 27 '22 14:10

Joma


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!

like image 43
grokky Avatar answered Oct 27 '22 13:10

grokky


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.

like image 34
SledgeHammer Avatar answered Oct 27 '22 12:10

SledgeHammer


For EF Core 2:

dbContext.Database.ProviderName
like image 32
alignnc Avatar answered Oct 27 '22 14:10

alignnc