Connection Strings
ABP Framework is designed to be modular, microservice compatible and multi-tenancy aware. Connection string management is also designed to support these scenarios;
- Allows to set separate connection strings for every module, so every module can have its own physical database. Modules even might be configured to use different DBMSs.
- Allows to set separate connection string and use a separate database per tenant (in a SaaS application).
It also supports hybrid scenarios;
- Allows to group modules into databases (all modules into a single shared database, 2 modules to database A, 3 modules to database B, 1 module to database C and rest of the modules to database D... etc.)
- Allows to group tenants into databases, just like the modules.
- Allows to separate databases per tenant per module (which might be harder to maintain for you because of too many databases, but the ABP framework supports it).
All the pre-built application modules are designed to be compatible these scenarios.
Configure the Connection Strings
See the following configuration:
"ConnectionStrings": {
"Default": "Server=localhost;Database=MyMainDb;Trusted_Connection=True;",
"AbpIdentityServer": "Server=localhost;Database=MyIdsDb;Trusted_Connection=True;",
"AbpPermissionManagement": "Server=localhost;Database=MyPermissionDb;Trusted_Connection=True;"
}
ABP uses the
IConfiguration
service to get the application configuration. While the simplest way to write configuration into theappsettings.json
file, it is not limited to this file. You can use environment variables, user secrets, Azure Key Vault... etc. See the configuration document for more.
This configuration defines three different connection strings:
MyMainDb
(theDefault
connection string) is the main connection string of the application. If you don't specify a connection string for a module, it fallbacks to theDefault
connection string. The application startup template is configured to use a single connection string, so all the modules uses a single shared database.MyIdsDb
is used by the IdentityServer module.MyPermissionDb
is used by the Permission Management module.
Pre-built application modules define constants for the connection string names. For example, the IdentityServer module defines a ConnectionStringName
constant in the AbpIdentityServerDbProperties
class (located in the Volo.Abp.IdentityServer
namespace). Other modules similarly define constants, so you can investigate the connection string name.
AbpDbConnectionOptions
ABP actually uses the AbpDbConnectionOptions
to get the connection strings. If you set the connection strings as explained above, AbpDbConnectionOptions
is automatically filled. However, you can set or override the connection strings using the options pattern. You can configure the AbpDbConnectionOptions
in the ConfigureServices
method of your module as shown below:
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpDbConnectionOptions>(options =>
{
options.ConnectionStrings.Default = "...";
options.ConnectionStrings["AbpPermissionManagement"] = "...";
});
}
Set the Connection String Name
A module typically has a unique connection string name associated to its DbContext
class using the ConnectionStringName
attribute. Example:
[ConnectionStringName("AbpIdentityServer")]
public class IdentityServerDbContext
: AbpDbContext<IdentityServerDbContext>, IIdentityServerDbContext
{
}
For Entity Framework Core and MongoDB, write this to your DbContext
class (and the interface if it has).
If you are developing a reusable, database provider independent module see also the best practices guide.
Database Migrations for the Entity Framework Core
Relational databases require to create the database and the database schema (tables, views... etc.) before using it.
The startup template (with EF Core ORM) comes with a single database and a .EntityFrameworkCore.DbMigrations
project that contains the migration files for that database. This project mainly defines a YourProjectNameMigrationsDbContext that calls the Configure...()
methods of the used modules, like builder.ConfigurePermissionManagement()
.
Once you want to separate a module's database, you typically will need to create a second migration path. The easiest way to create a copy of the .EntityFrameworkCore.DbMigrations
project with the DbContext
inside it, change its content to only call the Configure...()
methods of the modules needs to be stored in the second database and re-create the initial migration. In this case, you also need to change the .DbMigrator
application to be able to work with these second database too. In this way, you will have a separate migrations DbContext per database.
Multi-Tenancy
See the multi-tenancy document to learn how to use separate databases for tenants.
Replace the Connection String Resolver
ABP defines the IConnectionStringResolver
and uses it whenever it needs a connection string. It has two pre-built implementations:
DefaultConnectionStringResolver
uses theAbpDbConnectionOptions
to select the connection string based on the rules defined in the "Configure the Connection Strings" section above.MultiTenantConnectionStringResolver
used for multi-tenant applications and tries to get the configured connection string for the current tenant if available. It uses theITenantStore
to find the connection strings. It inherits from theDefaultConnectionStringResolver
and fallbacks to the base logic if no connection string specified for the current tenant.
If you need a custom logic to determine the connection string, implement the IConnectionStringResolver
interface (optionally derive from the existing implementations) and replace the existing implementation using the dependency injection system.