mirror of https://github.com/abpframework/abp.git
1 changed files with 242 additions and 0 deletions
@ -0,0 +1,242 @@ |
|||||
|
# Layered Solution: Database configurations |
||||
|
|
||||
|
```json |
||||
|
//[doc-nav] |
||||
|
{ |
||||
|
"Previous": { |
||||
|
"Name": "Authentication", |
||||
|
"Path": "solution-templates/layered-web-application/authentication" |
||||
|
}, |
||||
|
"Next": { |
||||
|
"Name": "Logging (with Serilog)", |
||||
|
"Path": "solution-templates/layered-web-application/logging" |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
> Some of the features mentioned in this document may not be available in the free version. We're using the **\*** symbol to indicate that a feature is available in the **[Team](https://abp.io/pricing)** and **[Higher](https://abp.io/pricing)** licenses. |
||||
|
|
||||
|
ABP Studio's Layered Solution Template includes pre-configured database settings. This document explains how to manage database configurations in your solution. |
||||
|
|
||||
|
## Connection Strings |
||||
|
|
||||
|
Connection strings are stored in the `appsettings.json` file. You can customize them for different environments by modifying the respective `appsettings.json` files. The `*.DbMigrator` project and one of the [Web Application](web-applications.md) projects use the `Default` connection string by default. |
||||
|
|
||||
|
To change the connection string for the `Default` key, update the `appsettings.json` file in your project. Connection strings are defined under the `ConnectionStrings` section, as shown below: |
||||
|
|
||||
|
```json |
||||
|
{ |
||||
|
"ConnectionStrings": { |
||||
|
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=Bookstore;Trusted_Connection=True;TrustServerCertificate=true" |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### The DbContext Class |
||||
|
|
||||
|
In the `*.EntityFrameworkCore` project, the `DbContext` class is defined. The `DbContext` class is derived from the `AbpDbContext` class, which is a part of the ABP Framework. |
||||
|
|
||||
|
```csharp |
||||
|
[ReplaceDbContext(typeof(IIdentityProDbContext))] |
||||
|
[ReplaceDbContext(typeof(ISaasDbContext))] |
||||
|
[ConnectionStringName("Default")] |
||||
|
public class BookstoreDbContext : |
||||
|
AbpDbContext<BookstoreDbContext>, |
||||
|
ISaasDbContext, |
||||
|
IIdentityProDbContext |
||||
|
{ |
||||
|
#region Entities from the modules |
||||
|
|
||||
|
// Identity |
||||
|
public DbSet<IdentityUser> Users { get; set; } |
||||
|
public DbSet<IdentityRole> Roles { get; set; } |
||||
|
public DbSet<IdentityClaimType> ClaimTypes { get; set; } |
||||
|
public DbSet<OrganizationUnit> OrganizationUnits { get; set; } |
||||
|
public DbSet<IdentitySecurityLog> SecurityLogs { get; set; } |
||||
|
public DbSet<IdentityLinkUser> LinkUsers { get; set; } |
||||
|
public DbSet<IdentityUserDelegation> UserDelegations { get; set; } |
||||
|
public DbSet<IdentitySession> Sessions { get; set; } |
||||
|
|
||||
|
// SaaS |
||||
|
public DbSet<Tenant> Tenants { get; set; } |
||||
|
public DbSet<Edition> Editions { get; set; } |
||||
|
public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; } |
||||
|
|
||||
|
#endregion |
||||
|
|
||||
|
public BookstoreDbContext(DbContextOptions<BookstoreDbContext> options) |
||||
|
: base(options) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
protected override void OnModelCreating(ModelBuilder builder) |
||||
|
{ |
||||
|
base.OnModelCreating(builder); |
||||
|
|
||||
|
builder.ConfigurePermissionManagement(); |
||||
|
builder.ConfigureSettingManagement(); |
||||
|
builder.ConfigureBackgroundJobs(); |
||||
|
builder.ConfigureAuditLogging(); |
||||
|
builder.ConfigureFeatureManagement(); |
||||
|
builder.ConfigureIdentityPro(); |
||||
|
builder.ConfigureOpenIddictPro(); |
||||
|
builder.ConfigureLanguageManagement(); |
||||
|
builder.ConfigureSaas(); |
||||
|
builder.ConfigureTextTemplateManagement(); |
||||
|
builder.ConfigureGdpr(); |
||||
|
builder.ConfigureCmsKit(); |
||||
|
builder.ConfigureCmsKitPro(); |
||||
|
builder.ConfigureBlobStoring(); |
||||
|
|
||||
|
/* Configure your own tables/entities inside here */ |
||||
|
|
||||
|
//builder.Entity<YourEntity>(b => |
||||
|
//{ |
||||
|
// b.ToTable(BookstoreConsts.DbTablePrefix + "YourEntities", BookstoreConsts.DbSchema); |
||||
|
// b.ConfigureByConvention(); //auto configure for the base class props |
||||
|
// //... |
||||
|
//}); |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
#### ConnectionStringName Attribute |
||||
|
|
||||
|
We're using the *Default* connection string in the `BookstoreDbContext` class. You can change the connection string name by updating the `ConnectionStringName` attribute. |
||||
|
|
||||
|
```csharp |
||||
|
[ConnectionStringName("Default")] |
||||
|
``` |
||||
|
|
||||
|
[The `ConnectionStringName` attribute](../../framework/fundamentals/connection-strings.md#set-the-connection-string-name) defines the unique name of the connection string that is being used by that `DbContext` class. It matches with the connection string defined in the `appsettings.json` file. That name is also used in database migrations to distinguish different database schemas, and used as the key while storing tenant connection strings for a multi-tenant system. |
||||
|
|
||||
|
#### ReplaceDbContext Attribute |
||||
|
|
||||
|
```csharp |
||||
|
[ReplaceDbContext(typeof(IIdentityProDbContext))] |
||||
|
[ReplaceDbContext(typeof(ISaasDbContext))] |
||||
|
``` |
||||
|
|
||||
|
The application DbContext utilizes the [Identity](../../modules/identity.md) and [Saas **\***](../../modules/saas.md) modules and creates a single database that contains these modules database schemas. These modules define their own `DbContext` class normally. But [the `ReplaceDbContext` attribute](../../framework/data/entity-framework-core/index.md#replace-other-dbcontextes) tells to ABP to use this (`BookstoreDbContext`) `DbContext` class instead of the `DbContext` classes defined by these modules. Technically, it replaces the given `DbContext` classes on runtime. We are doing that to ensure that we have a single (merged) database schema, single database migration path and a single database transaction operation when we work these multiple modules. When we replace a `DbContext`, we should implement its interface as done with the `BookstoreDbContext` class: |
||||
|
|
||||
|
````csharp |
||||
|
public class BookstoreDbContext : |
||||
|
AbpDbContext<BookstoreDbContext>, |
||||
|
ISaasDbContext, |
||||
|
IIdentityProDbContext |
||||
|
```` |
||||
|
|
||||
|
* That class implements `ISaasDbContext` and `IIdentityProDbContext`, so these modules can use it. |
||||
|
|
||||
|
As the next part, the `BookstoreDbContext` class defines the following properties those are forced by the implemented interfaces: |
||||
|
|
||||
|
```csharp |
||||
|
// Identity |
||||
|
public DbSet<IdentityUser> Users { get; set; } |
||||
|
public DbSet<IdentityRole> Roles { get; set; } |
||||
|
public DbSet<IdentityClaimType> ClaimTypes { get; set; } |
||||
|
public DbSet<OrganizationUnit> OrganizationUnits { get; set; } |
||||
|
public DbSet<IdentitySecurityLog> SecurityLogs { get; set; } |
||||
|
public DbSet<IdentityLinkUser> LinkUsers { get; set; } |
||||
|
public DbSet<IdentityUserDelegation> UserDelegations { get; set; } |
||||
|
public DbSet<IdentitySession> Sessions { get; set; } |
||||
|
|
||||
|
// SaaS |
||||
|
public DbSet<Tenant> Tenants { get; set; } |
||||
|
public DbSet<Edition> Editions { get; set; } |
||||
|
public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; } |
||||
|
``` |
||||
|
|
||||
|
#### OnModelCreating Method |
||||
|
|
||||
|
The `OnModelCreating` method is used to configure the database schema. It calls the `Configure*` methods of the ABP Framework to configure the database schema for the modules. You can also configure your own tables/entities inside this method. |
||||
|
|
||||
|
```csharp |
||||
|
protected override void OnModelCreating(ModelBuilder builder) |
||||
|
{ |
||||
|
base.OnModelCreating(builder); |
||||
|
|
||||
|
builder.ConfigurePermissionManagement(); |
||||
|
builder.ConfigureSettingManagement(); |
||||
|
builder.ConfigureBackgroundJobs(); |
||||
|
builder.ConfigureAuditLogging(); |
||||
|
builder.ConfigureFeatureManagement(); |
||||
|
builder.ConfigureIdentityPro(); |
||||
|
builder.ConfigureOpenIddictPro(); |
||||
|
builder.ConfigureLanguageManagement(); |
||||
|
builder.ConfigureSaas(); |
||||
|
builder.ConfigureTextTemplateManagement(); |
||||
|
builder.ConfigureGdpr(); |
||||
|
builder.ConfigureCmsKit(); |
||||
|
builder.ConfigureCmsKitPro(); |
||||
|
builder.ConfigureBlobStoring(); |
||||
|
|
||||
|
/* Configure your own tables/entities inside here */ |
||||
|
|
||||
|
//builder.Entity<YourEntity>(b => |
||||
|
//{ |
||||
|
// b.ToTable(BookstoreConsts.DbTablePrefix + "YourEntities", BookstoreConsts.DbSchema); |
||||
|
// b.ConfigureByConvention(); //auto configure for the base class props |
||||
|
// //... |
||||
|
//}); |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
> The `Configure*` methods are extension methods defined in each module's `EntityFrameworkCore` project. These methods are used to configure the database schema for their respective modules. At runtime, the `DbContext` class is replaced by the `BookstoreDbContext` class only for the `DbContext` classes that use the `ReplaceDbContext` attribute. For other modules, their own dedicated `DbContext` classes are used without replacement. |
||||
|
|
||||
|
### The `IDesignTimeDbContextFactory` Implementation |
||||
|
|
||||
|
The `IDesignTimeDbContextFactory` interface is used to create a `DbContext` instance at design time. It is used by EF Core tools to create migrations and update the database. The `BookstoreDbContextFactory` class implements the `IDesignTimeDbContextFactory` interface to create a `BookstoreMigrationsDbContext` instance. |
||||
|
|
||||
|
```csharp |
||||
|
public class BookstoreDbContextFactory : IDesignTimeDbContextFactory<BookstoreDbContext> |
||||
|
{ |
||||
|
public BookstoreDbContext CreateDbContext(string[] args) |
||||
|
{ |
||||
|
var configuration = BuildConfiguration(); |
||||
|
|
||||
|
BookstoreEfCoreEntityExtensionMappings.Configure(); |
||||
|
|
||||
|
var builder = new DbContextOptionsBuilder<BookstoreDbContext>() |
||||
|
.UseSqlServer(configuration.GetConnectionString("Default")); |
||||
|
|
||||
|
return new BookstoreDbContext(builder.Options); |
||||
|
} |
||||
|
|
||||
|
private static IConfigurationRoot BuildConfiguration() |
||||
|
{ |
||||
|
var builder = new ConfigurationBuilder() |
||||
|
.SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../Acme.Bookstore.DbMigrator/")) |
||||
|
.AddJsonFile("appsettings.json", optional: false); |
||||
|
|
||||
|
return builder.Build(); |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### Configuration |
||||
|
|
||||
|
In the `*.EntityFrameworkCore` project, the `BookstoreEntityFrameworkCoreModule` class is used to configure the database context. |
||||
|
|
||||
|
```csharp |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddAbpDbContext<BookstoreDbContext>(options => |
||||
|
{ |
||||
|
/* Remove "includeAllEntities: true" to create |
||||
|
* default repositories only for aggregate roots */ |
||||
|
options.AddDefaultRepositories(includeAllEntities: true); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpDbContextOptions>(options => |
||||
|
{ |
||||
|
/* The main point to change your DBMS. |
||||
|
* See also BookstoreDbContextFactory for EF Core tooling. */ |
||||
|
options.UseSqlServer(); |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
We are basically setting the SQL Server as the default DBMS for this application. and registering the `BookstoreDbContext` class to the [dependency injection](../../framework/fundamentals/dependency-injection.md) system. |
||||
Loading…
Reference in new issue