You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
> Actual solution structure may be a bit different based on your preferences, but the database part will be same.
23
+
Actual solution structure may be a bit different based on your preferences, but the database part will be same.
24
+
25
+
> This document will use the `Acme.BookStore` example project name to refer the projects and classes. You need to find the corresponding class/project in your solution.
24
26
25
27
### The Database Structure
26
28
27
-
The startup template has some [application modules](Modules/Index.md) pre-installed. Each layer of the solution has corresponding module package references. So, the `.EntityFrameworkCore` project has the NuGet references for the `.EntityFrameworkCore` packages of the used modules:
29
+
The startup template has some [application modules](Modules/Index.md) pre-installed. Each layer of the solution has corresponding module **package references**. So, the `.EntityFrameworkCore` project has the NuGet references for the `.EntityFrameworkCore` packages of the used modules:
In this way, you collect all the EF Core dependencies under the `.EntityFrameworkCore` project.
33
+
In this way, you collect all the **EF Core dependencies** under the `.EntityFrameworkCore` project.
32
34
33
-
> In addition to the module references, it references to the `Volo.Abp.EntityFrameworkCore.SqlServer` package since the startup template is pre-configured for the SQL Server. See the documentation if you want to [switch to another DBMS](Entity-Framework-Core-Other-DBMS.md).
35
+
> In addition to the module references, it references to the `Volo.Abp.EntityFrameworkCore.SqlServer` package since the startup template is pre-configured for the **SQL Server**. See the documentation if you want to [switch to another DBMS](Entity-Framework-Core-Other-DBMS.md).
34
36
35
37
While every module has its own `DbContext` class by design and can use its **own physical database**, the solution is configured to use a **single shared database** as shown in the figure below:
36
38
@@ -57,13 +59,13 @@ ABP Framework's [connection string](Connection-Strings.md) system allows you to
57
59
58
60
The example configuration about tells to the ABP Framework to use the second connection string for the [Audit Logging module](Modules/Audit-Logging.md).
59
61
60
-
However, this is just the beginning. You also need to create the second database, create audit log tables inside it and maintain the database tables using the code first approach. One of the main purposes of this document is to guide you on such database separation scenarios.
62
+
**However, this is just the beginning**. You also need to create the second database, create audit log tables inside it and maintain the database tables using the code first migrations approach. One of the main purposes of this document is to guide you on such **database separation** scenarios.
61
63
62
64
#### Module Tables
63
65
64
66
Every module uses its own databases tables. For example, the [Identity Module](Modules/Identity.md) has some tables to manage the users and roles in the system.
65
67
66
-
#### Table Prefixes
68
+
#####Table Prefixes
67
69
68
70
Since it is allowed to share a single database by all modules (it is the default configuration), a module typically uses a prefix to group its own tables.
69
71
@@ -661,7 +663,9 @@ You can just copy & modify the content of the original `.DbMigrations` project.
661
663
Create a new DbContext for the migrations and call the extension methods to configure database tables for the related modules:
@@ -682,6 +686,8 @@ public class BookStoreSecondMigrationsDbContext : AbpDbContext<BookStoreSecondMi
682
686
}
683
687
````
684
688
689
+
> `[ConnectionStringName(...)]` attribute is important here and tells to the ABP Framework which connection string should be used for this `DbContext`.
690
+
685
691
Create a Design Time Db Factory class, that is used by the EF Core tooling (by `Add-Migration` and `Update-Database` PCM commands for example):
686
692
687
693
````csharp
@@ -778,3 +784,138 @@ Run the `Update-Database` command to delete the tables from your main database.
778
784
779
785
Notice that you've also **deleted some initial seed data** (for example, permission grants for the admin role) if you haven't copied it to the new database. If you run the application, you may not login anymore. The solution is simple: **Re-run the `.DbMigrator` console application** in your solution, it will seed the new database.
780
786
787
+
### Automate the Second Database Schema Migration
788
+
789
+
`.DbMigrator` console application can run the seed code across multiple databases, without any additional configuration. However, it can not run the EF Core Code First Migrations inside the second database migration project. Now, you will see how to configure the console migration application to handle both databases.
790
+
791
+
#### Implementing the IBookStoreDbSchemaMigrator
792
+
793
+
`EntityFrameworkCoreBookStoreDbSchemaMigrator` class inside the `Acme.BookStore.EntityFrameworkCore.DbMigrations` project is responsible to migrate the database schema for the `BookStoreMigrationsDbContext`. It should be like that:
It implements the `IBookStoreDbSchemaMigrator` and replaces existing services (see the first line).
825
+
826
+
Remove the `[Dependency(ReplaceServices = true)]` line, because we will have two implementations of this interface and we want to use both. We don't want to replace one of them.
827
+
828
+
Create a copy of this class inside the new migration project (`Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb`), but use the `BookStoreSecondMigrationsDbContext`. Example implementation:
> Name of this class is important for [dependency injection](Dependency-Injection.md). It should end with `BookStoreDbSchemaMigrator` to be injectable by `IBookStoreDbSchemaMigrator` reference.
859
+
860
+
We, now, have two implementations of the `IBookStoreDbSchemaMigrator` interface, each one responsible to migrate the related database schema.
861
+
862
+
#### Define a Module Class for the Second Migration Project
863
+
864
+
It is time to define the module class for this second migrations (`Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb`) project:
Now, reference `Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb` project from the `Acme.BookStore.DbMigrator` project and `typeof(BookStoreEntityFrameworkCoreSecondDbMigrationsModule)` to the dependency list of the `BookStoreDbMigratorModule`. `BookStoreDbMigratorModule` class should be something like that:
We had a reference to the `Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb` project from the `Acme.BookStore.Web` project, but hadn't added module dependency since we hadn't created it yet. But, now we have it and we need to add `typeof(BookStoreEntityFrameworkCoreSecondDbMigrationsModule)` to the dependency list of the `BookStoreWebModule` class.
895
+
896
+
#### BookStoreDbMigrationService
897
+
898
+
You need one final touch to the `BookStoreDbMigrationService` inside the `Acme.BookStore.Domain` project. It is currently designed to work with a single `IBookStoreDbSchemaMigrator` implementation, but now we have two.
899
+
900
+
It injects `IBookStoreDbSchemaMigrator`. Replace it with an `IEnumerable<IBookStoreDbSchemaMigrator>` injection.
901
+
902
+
Now, you have a collection of migrators instead of a single one. Find the lines like:
903
+
904
+
````csharp
905
+
await_dbSchemaMigrators.MigrateAsync();
906
+
````
907
+
908
+
change them to:
909
+
910
+
````csharp
911
+
foreach (varmigratorin_dbSchemaMigrators)
912
+
{
913
+
awaitmigrator.MigrateAsync();
914
+
}
915
+
````
916
+
917
+
You can run the `.DbMigrator` application to migrate & seed the databases. To test, you can delete both databases and run the application to see if they are created.
918
+
919
+
## Conclusion
920
+
921
+
This document explains how to split your databases and manage your database migrations of your solution for Entity Framework Core. In brief, you need to have a separate migration project per different databases.
Copy file name to clipboardexpand all lines: samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/EntityFrameworkCoreBookStoreDbSchemaMigrator.cs
Copy file name to clipboardexpand all lines: samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb/EntityFrameworkCore/BookStoreSecondMigrationsDbContext.cs
Copy file name to clipboardexpand all lines: samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrationsForSecondDb/EntityFrameworkCore/EntityFrameworkCoreBookStoreSecondDbSchemaMigrator.cs
0 commit comments