diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json index 9c00e584ab..5ebdf0b2eb 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json @@ -53,6 +53,7 @@ "CreateANugetPackage": "Create a Nuget package", "AddNew": "Add new", "PackageAlreadyExist{0}": "\"{0}\" package is already added.", + "ModuleAlreadyExist{0}": "\"{0}\" module is already added.", "ClearCache": "Clear cache", "SuccessfullyCleared": "Successfully cleared", "Menu:NpmPackages": "NPM Packages", @@ -83,6 +84,7 @@ "This{0}AlreadyExistInThisOrganization": "This {0} already exist in this organization", "AreYouSureYouWantToDeleteAllComputers": "Are you sure you want to delete all computers?", "DeleteAll": "Delete all", - "DoYouWantToCreateNewUser": "Do you want to create new user?" + "DoYouWantToCreateNewUser": "Do you want to create new user?", + "MasterModules": "Master Modules" } } \ No newline at end of file diff --git a/docs/en/Entity-Framework-Core-Migrations.md b/docs/en/Entity-Framework-Core-Migrations.md new file mode 100644 index 0000000000..eb3125c13b --- /dev/null +++ b/docs/en/Entity-Framework-Core-Migrations.md @@ -0,0 +1,146 @@ +# EF Core Advanced Database Migrations + +This document begins by **introducing the default structure** provided by [the application startup template](Startup-Templates/Application.md) and **discusses various scenarios** you may want to implement for your own application. + +> This document is for who want to fully understand and customize the database structure comes with [the application startup template](Startup-Templates/Application.md). If you simply want to create entities and manage your code first migrations, just follow [the startup tutorials](Tutorials/Index.md). + +## About the EF Core Code First Migrations + +Entity Framework Core provides an easy to use and powerful [database migration system](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/). ABP Framework [startup templates](Startup-Templates/Index.md) take the advantage of this system to allow you to develop your application in a standard way. + +However, EF Core migration system is **not so good in a modular environment** where each module maintains its **own database schema** while two or more modules may **share a single database** in practical. + +Since ABP Framework cares about modularity in all aspects, it provides a **solution** to this problem. It is important to understand this solution if you need to **customize your database structure**. + +> See [EF Core's own documentation](https://docs.microsoft.com/en-us/ef/core/managing-schemas/migrations/) to fully learn the EF Core Code First Migrations and why you need to such a system. + +## The Default Solution & Database Configuration + +When you [create a new web application](https://abp.io/get-started) (with EF Core, which is the default database provider), your solution structure will be similar to the picture below: + +![bookstore-visual-studio-solution-v3](images/bookstore-visual-studio-solution-v3.png) + +> Actual solution structure may be a bit different based on your preferences, but the database part will be same. + +### The Database Structure + +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: + +![bookstore-efcore-dependencies](images/bookstore-efcore-dependencies.png) + +In this way, you collect all the EF Core dependencies under the `.EntityFrameworkCore` project. + +> 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). + +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: + +![single-database-usage](images/single-database-usage.png) + +This is **the simplest configuration** and suitable for most of the applications. `appsettings.json` file has a **single connection string**, named `Default`: + +````json +"ConnectionStrings": { + "Default": "..." +} +```` + +So, you have a **single database schema** which contains all the tables of the modules **sharing** this database. + +ABP Framework's [connection string](Connection-Strings.md) system allows you to easily **set a different connection string** for a desired module: + +````json +"ConnectionStrings": { + "Default": "...", + "AbpAuditLogging": "..." +} +```` + +The example configuration about tells to the ABP Framework to use the second connection string for the [Audit Logging module](Modules/Audit-Logging.md). + +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. + +#### Module Tables + +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. + +#### Table Prefixes + +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. + +The fundamental modules, like [Identity](Modules/Identity.md), [Tenant Management](Modules/Tenant-Management.md) and [Audit Logs](Modules/Audit-Logging.md), use the `Abp` prefix, while some other modules use their own prefixes. [Identity Server](Modules/IdentityServer.md) module uses the `IdentityServer` prefix for example. + +If you want, you can change the database table name prefix for a module for your application. Example: + +````csharp +Volo.Abp.IdentityServer.AbpIdentityServerDbProperties.DbTablePrefix = "Ids"; +```` + +This code changes the prefix of the [Identity Server](Modules/IdentityServer.md) module. Write this code at the very beginning in your application. + +> Every module also defines `DbSchema` property (near to `DbTablePrefix`), so you can set it for the databases support the schema usage. + +### The Projects + +From the database point of view, there are three important projects those will be explained in the next sections. + +#### .EntityFrameworkCore Project + +This project has the `DbContext` class (`BookStoreDbContext` for this sample) of your application. You typically use this `DbContext` in your application code (in your custom [repositories](Repositories.md) if you follow the best practices). + +It is almost an empty `DbContext` since your application don't have any entities at the beginning, except the pre-defined `AppUser` entity: + +````csharp +[ConnectionStringName("Default")] +public class BookStoreDbContext : AbpDbContext +{ + public DbSet Users { get; set; } + + /* Add DbSet properties for your Aggregate Roots / Entities here. */ + + public BookStoreDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + /* Configure the shared tables (with included modules) here */ + + builder.Entity(b => + { + //Sharing the same table "AbpUsers" with the IdentityUser + b.ToTable("AbpUsers"); + + //Configure base properties + b.ConfigureByConvention(); + b.ConfigureAbpUser(); + + //Moved customization of the "AbpUsers" table to an extension method + b.ConfigureCustomUserProperties(); + }); + + /* Configure your own tables/entities inside the ConfigureBookStore method */ + builder.ConfigureBookStore(); + } +} +```` + +This simple `DbContext` class still needs some explanations: + +* It defines a `[ConnectionStringName]` attribute which tells ABP to always use the `Default` connection string for this `Dbcontext`. +* It inherits from the `AbpDbContext` instead of the standard `DbContext` class. You can see the [EF Core integration](Entity-Framework-Core.md) document for more. For now, know that the `AbpDbContext` base class implements some conventions of the ABP Framework to automate some common tasks for you. +* It declares a `DbSet` property for the `AppUser` entity. `AppUser` shares the same table (named `AbpUsers` by default) with the `IdentityUser` entity of the [Identity module](Modules/Identity.md). The startup template provides this entity inside the application since we think that the User entity is generally needs to be customized in your application. +* The constructor takes a `DbContextOptions` instance. +* It overrides the `OnModelCreating` method to define the EF Core mappings. + * It first calls the the `base.OnModelCreating` method to let the ABP Framework to implement the base mappings for us. + * It then configures the mapping for the `AppUser` entity. There is a special case for this entity, which will be explained in the next sections. + * It finally calls the `builder.ConfigureBookStore()` extension method to configure other entities of your application. + +This design will be explained in more details after introducing the other database related projects. + +#### .EntityFrameworkCore.DbMigrations Project + +TODO \ No newline at end of file diff --git a/docs/en/Entity-Framework-Core-Other-DBMS.md b/docs/en/Entity-Framework-Core-Other-DBMS.md index 854309d070..a08ac6d169 100644 --- a/docs/en/Entity-Framework-Core-Other-DBMS.md +++ b/docs/en/Entity-Framework-Core-Other-DBMS.md @@ -1,12 +1,16 @@ -# Switch to another DBMS for Entity Framework Core +# Switch to Another DBMS for Entity Framework Core -**[The application startup template](Startup-Templates/Application.md)** comes with SQL Server provider pre-configured for the Entity Framework Core. Entity Framework Core supports [many other DBMSs](https://docs.microsoft.com/en-us/ef/core/providers/) and you can use any of them with your ABP based applications. +**[The application startup template](Startup-Templates/Application.md)** comes with **SQL Server provider pre-configured** for the Entity Framework Core. However, EF Core supports [many other DBMSs](https://docs.microsoft.com/en-us/ef/core/providers/) and you can use any of them within your ABP based applications. -ABP framework provides integration packages for some common DBMSs to make the configuration a bit easier (see the [entity framework core document](Entity-Framework-Core.md) for a list of available integration packages). However, you can configure your DBMS provider without these integration packages. +ABP framework provides **integration packages** for some common DBMSs to make the configuration a bit easier. You can use the following documents to learn how to **switch to your favorite DBMS**: -While using the integration package is always recommended (it also makes standard for the depended version across different modules), you can do it manually if there is no integration package for your DBMS provider. +* [MySQL](Entity-Framework-Core-MySQL.md) +* [PostgreSQL](Entity-Framework-Core-PostgreSQL.md) +* [SQLite](Entity-Framework-Core-SQLite.md) -This document explains how to switch to MySQL without using [the MySQL integration package](Entity-Framework-Core-MySQL.md). +However, you can configure your DBMS provider **without** these integration packages. While using the integration package is always recommended (it also makes standard for the depended version across different modules), you can do it manually if there is no integration package for your DBMS provider. + +For an example, this document explains how to switch to MySQL without using [the MySQL integration package](Entity-Framework-Core-MySQL.md). ## Replace the SQL Server Dependency diff --git a/docs/en/Entity-Framework-Core.md b/docs/en/Entity-Framework-Core.md index 586c8d4a01..788f3234ed 100644 --- a/docs/en/Entity-Framework-Core.md +++ b/docs/en/Entity-Framework-Core.md @@ -32,14 +32,9 @@ namespace MyCompany.MyProject Entity Framework Core supports various database management systems ([see all](https://docs.microsoft.com/en-us/ef/core/providers/)). ABP framework and this document doesn't depend on any specific DBMS. -If you are creating a reusable library, avoid to depend on a specific DBMS package. However, in a final application you eventually will select a DBMS. +If you are creating a [reusable application module](Modules/Index.md), avoid to depend on a specific DBMS package. However, in a final application you eventually will select a DBMS. -ABP framework provides integration packages for some common DBMSs to make the configuration a bit easier. [The startup templates](Startup-Templates/Index.md) come with **SQL Server (localdb) pre-configured**. See the following documents to learn how to configure for the other DBMS providers: - -* [MySQL](Entity-Framework-Core-MySQL.md) -* [PostgreSQL](Entity-Framework-Core-PostgreSQL.md) -* [SQLite](Entity-Framework-Core-SQLite.md) -* [Others](Entity-Framework-Core-Other-DBMS.md) +See [Switch to Another DBMS for Entity Framework Core](Entity-Framework-Core-Other-DBMS.md) document to learn how to switch the DBMS. ## Creating DbContext diff --git a/docs/en/Exception-Handling.md b/docs/en/Exception-Handling.md index 93bad2b6ed..0e0a530416 100644 --- a/docs/en/Exception-Handling.md +++ b/docs/en/Exception-Handling.md @@ -204,7 +204,7 @@ Instead of localizing the message while throwing the exception, you can separate First, define the **code-namespace** to **localization resource** mapping in the module configuration: ````C# -services.Configure(options => +services.Configure(options => { options.MapCodeNamespace("Volo.Qa", typeof(QaResource)); }); @@ -285,7 +285,7 @@ The `IHttpExceptionStatusCodeFinder` is used to automatically determine the HTTP Automatic HTTP status code determination can be overrided by custom mappings. For example: ````C# -services.Configure(options => +services.Configure(options => { options.Map("Volo.Qa:010002", HttpStatusCode.Conflict); }); diff --git a/docs/en/Modules/Identity.md b/docs/en/Modules/Identity.md new file mode 100644 index 0000000000..028144c624 --- /dev/null +++ b/docs/en/Modules/Identity.md @@ -0,0 +1,4 @@ +# Identity Management Module + +See [the source code](https://github.com/abpframework/abp/tree/dev/modules/identity). Documentation will come soon... + diff --git a/docs/en/Modules/Tenant-Management.md b/docs/en/Modules/Tenant-Management.md new file mode 100644 index 0000000000..73e16aee8e --- /dev/null +++ b/docs/en/Modules/Tenant-Management.md @@ -0,0 +1,3 @@ +# Tenant Management Module + +TODO \ No newline at end of file diff --git a/docs/en/Tutorials/Index.md b/docs/en/Tutorials/Index.md new file mode 100644 index 0000000000..7391b6303e --- /dev/null +++ b/docs/en/Tutorials/Index.md @@ -0,0 +1,6 @@ +# Tutorials + +## Application Development + +* [With ASP.NET Core MVC / Razor Pages UI](AspNetCore-Mvc/Part-I.md) +* [With Angular UI](Angular/Part-I.md) diff --git a/docs/en/_resources/Diagrams.docx b/docs/en/_resources/Diagrams.docx new file mode 100644 index 0000000000..792d473e3f Binary files /dev/null and b/docs/en/_resources/Diagrams.docx differ diff --git a/docs/en/docs-nav.json b/docs/en/docs-nav.json index cbb4c80e72..0de3be1651 100644 --- a/docs/en/docs-nav.json +++ b/docs/en/docs-nav.json @@ -33,6 +33,7 @@ }, { "text": "Tutorials", + "path": "Tutorials/Index.md", "items": [ { "text": "Application Development", @@ -295,20 +296,22 @@ "path": "Entity-Framework-Core.md", "items": [ { - "text": "Switch to MySQL", - "path": "Entity-Framework-Core-MySQL.md" - }, - { - "text": "Switch to PostgreSQL", - "path": "Entity-Framework-Core-PostgreSQL.md" - }, - { - "text": "Switch to SQLite", - "path": "Entity-Framework-Core-SQLite.md" - }, - { - "text": "Switch to another DBMS", - "path": "Entity-Framework-Core-Other-DBMS.md" + "text": "Switch DBMS", + "path": "Entity-Framework-Core-Other-DBMS.md", + "items": [ + { + "text": "To MySQL", + "path": "Entity-Framework-Core-MySQL.md" + }, + { + "text": "To PostgreSQL", + "path": "Entity-Framework-Core-PostgreSQL.md" + }, + { + "text": "To SQLite", + "path": "Entity-Framework-Core-SQLite.md" + } + ] } ] }, diff --git a/docs/en/images/bookstore-efcore-dependencies.png b/docs/en/images/bookstore-efcore-dependencies.png new file mode 100644 index 0000000000..3de5a679ef Binary files /dev/null and b/docs/en/images/bookstore-efcore-dependencies.png differ diff --git a/docs/en/images/single-database-usage.png b/docs/en/images/single-database-usage.png new file mode 100644 index 0000000000..108173fd86 Binary files /dev/null and b/docs/en/images/single-database-usage.png differ diff --git a/docs/zh-Hans/Exception-Handling.md b/docs/zh-Hans/Exception-Handling.md index a251c50f61..36f959f312 100644 --- a/docs/zh-Hans/Exception-Handling.md +++ b/docs/zh-Hans/Exception-Handling.md @@ -204,7 +204,7 @@ throw new UserFriendlyException(_stringLocalizer["UserNameShouldBeUniqueMessage" 首先,在模块配置代码中将 **code-namespace** 映射至 **本地化资源**: ````C# -services.Configure(options => +services.Configure(options => { options.MapCodeNamespace("Volo.Qa", typeof(QaResource)); }); @@ -285,7 +285,7 @@ ABP尝试按照以下规则,自动映射常见的异常类型的HTTP状态代码 可以重写HTTP状态代码的自动映射,示例如下: ````C# -services.Configure(options => +services.Configure(options => { options.Map("Volo.Qa:010002", HttpStatusCode.Conflict); }); diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRootWithUser.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRootWithUser.cs index b2dbb8c280..c6bfefbb23 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRootWithUser.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedAggregateRootWithUser.cs @@ -15,10 +15,10 @@ namespace Volo.Abp.Domain.Entities.Auditing public virtual TUser Deleter { get; set; } /// - public TUser Creator { get; set; } + public virtual TUser Creator { get; set; } /// - public TUser LastModifier { get; set; } + public virtual TUser LastModifier { get; set; } } /// @@ -34,10 +34,10 @@ namespace Volo.Abp.Domain.Entities.Auditing public virtual TUser Deleter { get; set; } /// - public TUser Creator { get; set; } + public virtual TUser Creator { get; set; } /// - public TUser LastModifier { get; set; } + public virtual TUser LastModifier { get; set; } protected FullAuditedAggregateRootWithUser() { diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntityWithUser.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntityWithUser.cs index 3156813843..f7ec2b672f 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntityWithUser.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Entities/Auditing/FullAuditedEntityWithUser.cs @@ -15,10 +15,10 @@ namespace Volo.Abp.Domain.Entities.Auditing public virtual TUser Deleter { get; set; } /// - public TUser Creator { get; set; } + public virtual TUser Creator { get; set; } /// - public TUser LastModifier { get; set; } + public virtual TUser LastModifier { get; set; } } /// @@ -34,10 +34,10 @@ namespace Volo.Abp.Domain.Entities.Auditing public virtual TUser Deleter { get; set; } /// - public TUser Creator { get; set; } + public virtual TUser Creator { get; set; } /// - public TUser LastModifier { get; set; } + public virtual TUser LastModifier { get; set; } protected FullAuditedEntityWithUser() {