diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json index 58e4b561d6..db8676a3e0 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json @@ -196,14 +196,14 @@ "WhatHappensWhenLicenseEndsExplanation4": "You can not install new modules and themes added to the ABP Commercial platform after your license ends.", "WhatHappensWhenLicenseEndsExplanation5": "You can not use the ABP Suite.", "WhatHappensWhenLicenseEndsExplanation6": "You can not get the premium support anymore.", - "WhatHappensWhenLicenseEndsExplanation7": "You can renew your subscription if you want to continue to get these benefits. There is a 20% discount when you renew your subscription.", + "WhatHappensWhenLicenseEndsExplanation7": "You can renew your subscription if you want to continue to get these benefits. If you renew your subscription within 1 month after your license expires, a 20% discount is applied.", "WhenShouldIRenewMyLicense": "When should I renew my license?", - "WhenShouldIRenewMyLicenseExplanation1": "If you renew your license within 1 month after your license expires, %20 discount will be applied to total license price.", + "WhenShouldIRenewMyLicenseExplanation1": "If you renew your license within 1 month after your license expires, a %20 discount is be applied.", "WhenShouldIRenewMyLicenseExplanation2": "If you renew your license after 1 month from your license expire date, the renew price will be same as license purchase price and there will be no discount for your renewal.", "TrialPlan": "Do you have a trial plan?", "TrialPlanExplanation": "For now, ABP Commercial doesn't have a trial plan. For the Team licenses we provide 30 days money back guarantee. You can just request a refund in the first 30 days. For the Business and Enterprise licenses, we provide 60% refund in 30 days. This is because Business and Enterprise licenses include the full source code of all the modules and the themes.", "DoYouAcceptBankWireTransfer": "Do you accept bank wire transfer?", - "DoYouAcceptBankWireTransferExplanation": "Yes, we accept bank wire transfer.
After sending the license amount via bank wire transfer, send us your receipt and the requested license type via e-mail.
Our international bank account information:", + "DoYouAcceptBankWireTransferExplanation": "Yes, we accept bank wire transfer.
After sending the license fee via bank transfer, email us at info@abp.io your receipt and the type of license requested. Our international bank account information:", "HowToUpgrade": "How to upgrade existing applications when a new version is available?", "HowToUpgradeExplanation1": "When you create a new application using ABP Commercial, all the modules and the theme are used as NuGet and NPM packages. So, you can easily upgrade the packages when a new version is available.", "HowToUpgradeExplanation2": "In addition to the standard NuGet/NPM upgrades, ABP CLI provides an update command that automatically finds and upgrades all ABP related packages in your solution.", diff --git a/common.props b/common.props index d7d4fd2a05..6bad8e8068 100644 --- a/common.props +++ b/common.props @@ -1,7 +1,7 @@ latest - 4.4.0-rc.2 + 5.0.0 $(NoWarn);CS1591;CS0436 https://abp.io/assets/abp_nupkg.png https://abp.io/ diff --git a/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/POST.md b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/POST.md new file mode 100644 index 0000000000..dff6d1af77 --- /dev/null +++ b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/POST.md @@ -0,0 +1,174 @@ +# ABP Platform 4.4 RC Has Been Released + +Today, we have released the [ABP Framework](https://abp.io/) and the [ABP Commercial](https://commercial.abp.io/) version 4.4 RC (Release Candidate). This blog post introduces the new features and important changes in this new version. + +> **The planned release date for the [4.4.0 final](https://github.com/abpframework/abp/milestone/53) version is July 13, 2021**. + +## Get Started with the 4.4 RC + +If you want to try the version 4.4.0 today, follow the steps below; + +1) **Upgrade** the ABP CLI to the version `4.4.0-rc.1` using a command line terminal: + +````bash +dotnet tool update Volo.Abp.Cli -g --version 4.4.0-rc.1 +```` + +**or install** if you haven't installed before: + +````bash +dotnet tool install Volo.Abp.Cli -g --version 4.4.0-rc.1 +```` + +2) Create a **new application** with the `--preview` option: + +````bash +abp new BookStore --preview +```` + +See the [ABP CLI documentation](https://docs.abp.io/en/abp/latest/CLI) for all the available options. + +> You can also use the *Direct Download* tab on the [Get Started](https://abp.io/get-started) page by selecting the **Preview checkbox**. + +### Migration Notes + +There is **no breaking change** with this version. However, if you are using Entity Framework Core, you will need to run the `Add-Migration` command to add a new **database migration** since some changes done in the module database mappings. + +## What's new with the ABP Framework 4.4 + +### Removed EntityFrameworkCore.DbMigrations Project + +With this version, we are doing an important change in the application startup solution template. The startup solution was containing an `EntityFrameworkCore.DbMigrations` project that contains a separate `DbContext` class which was responsible to unify the module database mappings and maintain the code-first database migrations. With the v4.4, we've removed that project from the solution. In the new structure, the `EntityFrameworkCore` integration project will be used for database migrations as well as on runtime. + +We'd published [a community article](https://community.abp.io/articles/unifying-dbcontexts-for-ef-core-removing-the-ef-core-migrations-project-nsyhrtna) about that change. Please see the article to understand the motivation behind the change. + +Beside the `DbContext` unification, we've also used the new `ReplaceDbContext` attribute and [replaced](https://github.com/abpframework/abp/blob/ea2205f0855f52015152ae066a5c239af4b8511f/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/EntityFrameworkCore/MyProjectNameDbContext.cs#L18-L19) the `IIdentityDbContext` and `ITenantManagementDbContext` interfaces to make it possible to perform join queries over repositories for these modules easily. In the next days, we will publish another community article to explain the problem and the solution. However, most of times, you don't need to know these details. + +### Dynamic Menu Management for the CMS Kit Module + +CMS Kit is a set of reusable *Content Management System* features packaged as an ABP application module. We had published the first usable version with the previous release. With this release, we are adding another feature to the CMS Kit module: You can now dynamically arrange the main menu on the UI, which is an essential feature for any kind of content management system. In this way, you can add pages or any kind of arbitrary URLs to the main menu from the UI. + +A screenshot from the menu management page (from the CMS Kit admin side): + +![menu-items-admin](menu-items-admin.png) + +And the items rendered in a public website: + +![menu-items-public](menu-items-public.png) + +Note that this feature is also available with the open source [CMS Kit module](https://docs.abp.io/en/abp/4.4/Modules/Cms-Kit/Index) (while the screenshots have been taken from the ABP Commercial). + +### Razor Engine Support for Text Templating + +[Text Templating](https://docs.abp.io/en/abp/4.4/Text-Templating) is a system to generate content on runtime by using a model (data) and a template. It was running on the [Scriban](https://github.com/scriban/scriban) templating engine. Beginning from this version, we have a second option: We can use the familiar **razor syntax** to build and render the templates. See the text templating [razor integration document](https://docs.abp.io/en/abp/4.4/Text-Templating-Razor) to get started with the new engine! + +### New Customization Points for DbContext/Entities + +Two new extension methods are added to `ObjectExtensionManager.Instance` to override EF Core mappings of [pre-built application modules](https://docs.abp.io/en/abp/latest/Modules/Index). + +**Example: Change mappings for the `IdentityDbContext` to override mappings for the `IdentityUser` entity** + +````csharp +ObjectExtensionManager.Instance.MapEfCoreDbContext(modelBuilder => +{ + modelBuilder.Entity(b => + { + b.ToTable("MyUsers"); + b.Property(x => x.Email).HasMaxLength(300); + }); +}); +```` + +The startup template contains a class, like `YourProjectNameEfCoreEntityExtensionMappings`, that can be used to place that code. + +### New ABP CLI Commands + +There are new [ABP CLI](https://docs.abp.io/en/abp/4.4/CLI) commands introduced with the v4.4: + +* `abp install-libs` command is used for MVC / Razor Pages and Blazor Server applications to restore the `wwwroot/libs` folder. Previously we were running the `yarn` and `gulp` commands to restore that folder. While the `install-libs` command still uses yarn (if available), it is no longer needed to use `gulp`. +* `abp prompt` command can be used to open a prompt for the ABP CLI and run multiple commands without needing to specify the `abp` command every time. For example, if you run `abp prompt`, then you can directly run `install-libs` instead of `abp install-libs`. Use `exit` to quit from the ABP prompt. +* `abp batch` command can be used to run multiple ABP commands with one command. Prepare a text file, write each command as a line (without the `abp` command prefix), then execute `abp batch ` (ex: `abp batch your_commands.txt`) command to execute all the commands in that file. + +### appsettings.secrets.json + +Added `appsettings.secrets.json` to the startup template that can be used to set your sensitive/secret configuration values. You can ignore this file from source control (by adding to `.gitignore` if you're using git) and keep it only in developer/production machines. + +### Other ABP Framework Improvements + +* [#9350](https://github.com/abpframework/abp/pull/9350) Extracted `IRemoteServiceConfigurationProvider` to get remote service configurations. You can replace this service to get the configuration from any source. +* [#8829](https://github.com/abpframework/abp/pull/8829) Implemented error handler and retry for distributed event bus. +* [#9288](https://github.com/abpframework/abp/issues/9288) Use default CORS policy instead of a named one in the startup template. It is suggested to update your own solutions to make it simpler. +* Translated the framework and module localization strings to Hindi, Italian, Finnish and French languages. + +Beside these, there are a lot of enhancements and bug fixes. See the [4.4-preview milestone](https://github.com/abpframework/abp/milestone/52?closed=1) for all issues and pull requests closed with this version. + +## What's new with the ABP Commercial 4.4 + +### New Features for the SaaS Module + +We've implemented some important features to the [SaaS module](https://commercial.abp.io/modules/Volo.Saas): + +* Integrated to the [Payment module](https://commercial.abp.io/modules/Volo.Payment) and implemented **subscription system** for the SaaS module. +* Allow to make a **tenant active/passive**. In this way, you can take a tenant to passive to prevent the users of that tenant from using the system. In addition, you can set a date to automatically make a tenant passive when the date comes. +* Allow to **limit user count** for a tenant. +* Allow to set **different connection strings** for a tenant for each database/module, which makes possible to create different databases for a tenant for each microservice in a microservice solution. + +### New ABP Suite Code Generation Features + +There are many improvements done for for [ABP Suite](https://commercial.abp.io/tools/suite), including CRUD page generation for the **[microservice solution](https://docs.abp.io/en/commercial/latest/startup-templates/microservice/index) template**. + +### Angular UI: Two Factor Authentication for the Resource Owner Password Flow + +In the previous version, we had implemented the resource owner password authentication flow for the Angular UI, which makes the login process easier for simpler applications. With this release, we've implemented two-factor authentication for that flow. Authorization code flow already supports 2FA. + +### Other ABP Commercial Improvements + +* Added web layers to microservices in the microservice solution. You can use them to create modular UI or override existing pages/components of pre-built modules (e.g. Identity and SaaS). +* ABP Commercial license code has been moved to `appsettings.secrets.json` in the new startup templates. +* Added new language options: Hindi, Italian, Arabic, Finnish, French. + +Beside these, there are many minor improvements and fixes done in the modules and themes. + +## Other News + +In this section, I will share some news that you may be interested in. + +### New Article: Using Elsa Workflow with ABP Framework + +We have been frequently asked how to use [Elsa Workflows](https://elsa-workflows.github.io/elsa-core/) with the ABP Framework. Finally, we have [created an article](https://community.abp.io/articles/using-elsa-workflow-with-the-abp-framework-773siqi9) to demonstrate it. + +![elsa-overview](elsa-overview.gif) + +You can [check it](https://community.abp.io/articles/using-elsa-workflow-with-the-abp-framework-773siqi9) to see how to integrate Elsa into an ABP based solution easily. + +### Free E-Book: Implementing Domain Driven Design + +We've published a free e-book for the ABP Community in the beginning of June. This is a practical guide for implementing Domain Driven Design (DDD). While the implementation details are based on the ABP Framework infrastructure, the basic concepts, principles and models can be applied to any solution, even if it is not a .NET solution. + +![ddd-book](ddd-book.png) + +Thousands of copies are already downloaded. If you haven't seen it yet, [click here to get a free copy of that e-book](https://abp.io/books/implementing-domain-driven-design). + +### The LeptonX Theme + +We have been working on a new ABP theme, named the *LeptonX*, for a long time. The theme will be available for ABP Framework (free - lite version) and ABP Commercial (pro version). It is being finalized in the next weeks and we will release the first version in a short time. + +![leptonx](leptonx.png) + +See [this blog post](https://volosoft.com/blog/introducing-the-lepton-theme-next-generation) to learn more about that project. + +### Volosoft & .NET Foundation + +[Volosoft](https://volosoft.com/), the company leads the ABP Framework project, has been a corporate sponsor of the [.NET Foundation](https://dotnetfoundation.org/). We are happy by taking our place among other great sponsors! + +![dotnetfoundation-sponsor-volosoft](dotnetfoundation-sponsor-volosoft.png) + +We will continue to contribute to and support open source! See this [blog post for the announcement](https://volosoft.com/blog/Volosoft-Announces-the-NET-Foundation-Sponsorship). + +### Looking for Developer Advocate(s) + +We are actively looking for professional developer advocates for the ABP.IO platform. If you want to create content and touch to the ABP community, please check our [job post](https://github.com/volosoft/vs-home/issues/13). + +## About the Next Version + +The next version will be a major version: 5.0, which will be based on .NET 6.0. We are planning to release it in the end of 2021, short time after the .NET 6.0 release. We will release multiple preview/beta versions before the RC version. See the [road map](https://docs.abp.io/en/abp/latest/Road-Map) for details of the planned works for the version 5.0. diff --git a/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/abp-44-cover.png b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/abp-44-cover.png new file mode 100644 index 0000000000..1f231aac00 Binary files /dev/null and b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/abp-44-cover.png differ diff --git a/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/ddd-book.png b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/ddd-book.png new file mode 100644 index 0000000000..747fcc1d13 Binary files /dev/null and b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/ddd-book.png differ diff --git a/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/dotnetfoundation-sponsor-volosoft.png b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/dotnetfoundation-sponsor-volosoft.png new file mode 100644 index 0000000000..e1f70929f4 Binary files /dev/null and b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/dotnetfoundation-sponsor-volosoft.png differ diff --git a/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/elsa-overview.gif b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/elsa-overview.gif new file mode 100644 index 0000000000..ba589cabfc Binary files /dev/null and b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/elsa-overview.gif differ diff --git a/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/leptonx.png b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/leptonx.png new file mode 100644 index 0000000000..46faaf13e6 Binary files /dev/null and b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/leptonx.png differ diff --git a/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/menu-items-admin.png b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/menu-items-admin.png new file mode 100644 index 0000000000..63075eed70 Binary files /dev/null and b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/menu-items-admin.png differ diff --git a/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/menu-items-public.png b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/menu-items-public.png new file mode 100644 index 0000000000..42c12c6801 Binary files /dev/null and b/docs/en/Blog-Posts/2021-06-28 v4_4 Preview/menu-items-public.png differ diff --git a/docs/en/Blog-Posts/2021-07-08 Introducing_the_eShopOnAbp/POST.md b/docs/en/Blog-Posts/2021-07-08 Introducing_the_eShopOnAbp/POST.md new file mode 100644 index 0000000000..efba693145 --- /dev/null +++ b/docs/en/Blog-Posts/2021-07-08 Introducing_the_eShopOnAbp/POST.md @@ -0,0 +1,52 @@ +# Introducing the eShopOnAbp Project + +We are happy to introduce the **eShopOnAbp** project as an example microservice solution built with the ABP Framework by the core ABP team. This solution demonstrates the strength of ABP Framework and using it in a real-life case. The goal of the project is to create a full-featured cloud-native microservices reference application. The project is inspired by the [eShopOnContainers](https://github.com/dotnet-architecture/eShopOnContainers) project and shows how it can be implemented with the ABP Framework. + +> **Project Status**: Currently, the project doesn't have any business logic. We've just brought ABP's pre-built modules (Identity, Tenant Management, IdentityServer, etc) together as a base solution. However, it is fully working and you can now take it as a base solution for your microservice project. From now on, we will build the example application functionalities / business logic on top of it. + +## Source Code + +The source code is available on [abpframework/eShopOnAbp](https://github.com/abpframework/eShopOnAbp) repository. + +## The Big Picture + +The project follows micro-service architecture and overall structure is presented below. + +![eShopOnAbp Overall Solution](overall-solution.png) + +## How to Run? + +You can either run in Visual Studio, or using [Microsoft Tye](https://github.com/dotnet/tye). Tye is a developer tool that makes developing, testing, and deploying micro-services and distributed applications easier. + + ### Requirements + +- .NET 5.0+ +- Docker +- Yarn + +### Instructions + +- Clone the repository ( [eShopOnAbp](https://github.com/abpframework/eShopOnAbp) ) + +- Install Tye (*follow [these steps](https://github.com/dotnet/tye/blob/main/docs/getting_started.md#installing-tye)*) + +- Execute `run-tye.ps1` + +- Wait until all applications are up! + + - You can check running application from tye dashboard ([localhost:8000](http://127.0.0.1:8000/)) + +- After all your backend services are up, start the angular application: + + ```bash + cd apps/angular + yarn start + ``` + +## What's Next? + +We'll work on deployment & CI-CD processes as a next step and build the business logic on. First goal is deploying the entire application on [Kubernetes](https://kubernetes.io/). + +## Feedback + +Your comments and suggestions is important for us. You can ask your questions or post your feedback under [this discussion entry](https://github.com/abpframework/abp/discussions/9536). diff --git a/docs/en/Blog-Posts/2021-07-08 Introducing_the_eShopOnAbp/overall-solution.png b/docs/en/Blog-Posts/2021-07-08 Introducing_the_eShopOnAbp/overall-solution.png new file mode 100644 index 0000000000..e3ef175316 Binary files /dev/null and b/docs/en/Blog-Posts/2021-07-08 Introducing_the_eShopOnAbp/overall-solution.png differ diff --git a/docs/pt-BR/MongoDB.md b/docs/pt-BR/MongoDB.md new file mode 100644 index 0000000000..bc4a7882a7 --- /dev/null +++ b/docs/pt-BR/MongoDB.md @@ -0,0 +1,466 @@ +# Integração do MongoDB + +Este documento explica como integrar e configurar o MongoDB como um provedor de banco de dados para aplicações baseadas no ABP. + +## Instalação + +`Volo.Abp.MongoDB` é o pacote nuget principal para a integração do MongoDB. Instale-o em seu projeto (para uma aplicação em camadas, será sua camada de dados ou infraestrutura): + +``` +Install-Package Volo.Abp.MongoDB +``` + +Então adicione a dependência de módulo `AbpMongoDbModule` para o seu [module](Module-Development-Basics.md): + +```c# +using Volo.Abp.MongoDB; +using Volo.Abp.Modularity; + +namespace MyCompany.MyProject +{ + [DependsOn(typeof(AbpMongoDbModule))] + public class MyModule : AbpModule + { + // ... + } +} +``` + +## Criando um Mongo Db Context + +ABP apresenta o conceito **Mongo Db Context** (que é semelhante ao Entity Framework Core DbContext) para tornar mais fácil usar coleções e configurá-las. Um exemplo é mostrado abaixo: + +```c# +public class MyDbContext : AbpMongoDbContext +{ + public IMongoCollection Questions => Collection(); + + public IMongoCollection Categories => Collection(); + + protected override void CreateModel(IMongoModelBuilder modelBuilder) + { + base.CreateModel(modelBuilder); + + // Personalize a configuração para as suas collections. + } +} +``` + +* É derivado da classe `AbpMongoDbContext`. +* Adiciona uma propriedade pública `IMongoCollection` para cada mongo collection. Por padrão ABP usa essas propriedades para criar repositórios padrão. +* Substituir o método `CreateModel` permite definir a configuração da collection. + +### Configurar o Mapeamento para uma Collection + +ABP registra automaticamente entidades MongoDB client library para todas propriedades `IMongoCollection` em seu DbContext. Para o exemplo acima, as entidades `Question` e `Category` são registradas automaticamente. + +Para cada entidade registrada, chama `AutoMap()` e configura propriedades conhecidas de sua entidade. Por exemplo, se sua entidade implementa uma interface `IHasExtraProperties` (que já está implementada para cada raiz agregada por padrão), ele configura automaticamente `ExtraProperties`. + +Portanto, na maioria das vezes, você não precisa configurar explicitamente o registro de suas entidades. No entanto, se você precisar, pode fazer isso sobrescrevendo o método `CreateModel` em seu DbContext. Exemplo: + +````csharp +protected override void CreateModel(IMongoModelBuilder modelBuilder) +{ + base.CreateModel(modelBuilder); + + modelBuilder.Entity(b => + { + b.CollectionName = "MyQuestions"; // Define o nome da collection + b.BsonMap.UnmapProperty(x => x.MyProperty); // Ignora 'MyProperty' + }); +} +```` + +Este exemplo altera o nome da collection mapeada para 'MyQuestions' no banco de dados e ignora uma propriedade na classe `Question`. + +Se você só precisa configurar o nome da collection, você também pode usar o atributo `[MongoCollection]` para a collection em seu DbContext. Exemplo: + +````csharp +[MongoCollection("MyQuestions")] // Define o nome da collection +public IMongoCollection Questions => Collection(); +```` + +### Configurar a Seleção da String de Conexão + +Se você tiver vários bancos de dados em seu aplicativo, você pode configurar o nome da string de conexão para o seu DbContext usando o atributo `[ConnectionStringName]`. Exemplo: + +````csharp +[ConnectionStringName("MySecondConnString")] +public class MyDbContext : AbpMongoDbContext +{ + +} +```` + +Se você não configurar, a string de conexão `Default` é usada. Se você configurar um nome de string de conexão, mas não definir este nome da string de conexão na configuração da aplicação, então ele retorna para a string de conexão `Default`. + +## Registrando DbContext para Injeção de Dependência + +Use o método `AddAbpDbContext` em seu module para registrar sua classe DbContext para o sistema de [injeção de dependência](Dependency-Injection.md). + +```c# +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.MongoDB; +using Volo.Abp.Modularity; + +namespace MyCompany.MyProject +{ + [DependsOn(typeof(AbpMongoDbModule))] + public class MyModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddMongoDbContext(); + + // ... + } + } +} +``` + +### Adicionar Repositories Padrão + +O ABP pode criar automaticamente [repositories genéricas](Repositories.md) padrão para as entidades em seu DbContext. Basta usar a opção `AddDefaultRepositories()` no registro: + +````C# +services.AddMongoDbContext(options => +{ + options.AddDefaultRepositories(); +}); +```` + +Isso criará uma repository para cada [aggregate root entity](Entities.md) (classes derivadas de `AggregateRoot`) por padrão. Se você quiser criar repositories para outras entidades também, em seguida defina `includeAllEntities` para `true`: + +```c# +services.AddMongoDbContext(options => +{ + options.AddDefaultRepositories(includeAllEntities: true); +}); +``` + +Então você pode injetar e usar `IRepository` nas suas services. Suponha que você tenha uma entidade `Book` com a chave primária `Guid`: + +```csharp +public class Book : AggregateRoot +{ + public string Name { get; set; } + + public BookType Type { get; set; } +} +``` + +(`BookType` é um simples `enum` aqui) E você deseja criar uma nova entidade `Book` em uma [domain service](Domain-Services.md): + +```csharp +public class BookManager : DomainService +{ + private readonly IRepository _bookRepository; + + public BookManager(IRepository bookRepository) // injetar repositório padrão + { + _bookRepository = bookRepository; + } + + public async Task CreateBook(string name, BookType type) + { + Check.NotNullOrWhiteSpace(name, nameof(name)); + + var book = new Book + { + Id = GuidGenerator.Create(), + Name = name, + Type = type + }; + + await _bookRepository.InsertAsync(book); // Use um método de repositório padrão + + return book; + } +} +``` + +Este exemplo usa o método `InsertAsync` para inserir uma nova entity no banco de dados. + +### Adicionar Repositories Personalizadas + +Repositories genéricas padrão são poderosas e suficiente na maioria dos casos (uma vez que implementam `IQueryable`). No entanto, pode ser necessário criar uma repository customizada para adicionar seus próprios métodos de repository. + +Suponha que você deseja excluir todos os books por type. É sugerido definir uma interface para sua repository personalizada: + +```csharp +public interface IBookRepository : IRepository +{ + Task DeleteBooksByType( + BookType type, + CancellationToken cancellationToken = default(CancellationToken) + ); +} +``` + +Você geralmente vai querer derivar de `IRepository` para herdar métodos de repository padrão. No entanto, você não precisa. As interfaces de repository são definidas na camada de domínio de uma aplicação em camadas. Elas são implementadas na camada de dados ou infraestrutura (projeto `MongoDB` em um [startup template](https://abp.io/Templates)). + +Exemplo de implementação da interface `IBookRepository`: + +```csharp +public class BookRepository : + MongoDbRepository, + IBookRepository +{ + public BookRepository(IMongoDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async Task DeleteBooksByType( + BookType type, + CancellationToken cancellationToken = default(CancellationToken)) + { + var collection = await GetCollectionAsync(cancellationToken); + await collection.DeleteManyAsync( + Builders.Filter.Eq(b => b.Type, type), + cancellationToken + ); + } +} +``` + +Agora é possível [injetar](Dependency-Injection.md) a `IBookRepository` e usar o método `DeleteBooksByType` quando necessário. + +#### Substituir Repository Genérica Padrão + +Mesmo se você criar uma repository personalizada, você ainda pode injetar a repository genérica padrão (`IRepository` para este exemplo). A implementação da repository padrão não usará a classe que você criou. + +Se você querer substituir a implementação da repository padrão pela sua repository personalizada, faça dentro das opções `AddMongoDbContext`: + +```csharp +context.Services.AddMongoDbContext(options => +{ + options.AddDefaultRepositories(); + options.AddRepository(); //Replaces IRepository +}); +``` + +Isso é especialmente importante quando você deseja dar **override em um método da base repository** para customizar. Por exemplo, você pode querer substituir o método `DeleteAsync` para excluir uma entidade de uma forma mais eficiente: + +```csharp +public async override Task DeleteAsync( + Guid id, + bool autoSave = false, + CancellationToken cancellationToken = default) +{ + // TODO: Implementação customizada do método delete +} +``` + +### Acesso à API MongoDB + +Na maioria dos casos, você vai querer ocultar APIs do MongoDB atrás de uma repository (este é o objetivo principal da repository). No entanto, se você quiser acessar a API MongoDB através da Repository, você pode usar os métodos de extensão `GetDatabaseAsync()`, `GetCollectionAsync()` ou `GetAggregateAsync()`. Exemplo: + +```csharp +public class BookService +{ + private readonly IRepository _bookRepository; + + public BookService(IRepository bookRepository) + { + _bookRepository = bookRepository; + } + + public async Task FooAsync() + { + IMongoDatabase database = await _bookRepository.GetDatabaseAsync(); + IMongoCollection books = await _bookRepository.GetCollectionAsync(); + IAggregateFluent bookAggregate = await _bookRepository.GetAggregateAsync(); + } +} +``` + +> Importante: Você deve fazer referência ao pacote `Volo.Abp.MongoDB` do projeto que deseja acessar a API MongoDB. Isso quebra o encapsulamento, mas é o que você deseja nesse caso. + +### Transactions + +O MongoDB oferece suporte multi-document transactions a partir da versão 4.0 e o ABP Framework oferece suporte para isso. No entanto, o [startup template](Startup-templates/Index.md) **desativa** transactions por padrão. Se o seu **servidor** MongoDB suportar transactions, você pode habilitar esse recurso na classe *YourProjectMongoDbModule*: + +```csharp +Configure(options => +{ + options.TransactionBehavior = UnitOfWorkTransactionBehavior.Auto; +}); +``` + +> Ou você pode excluir este código, pois este já é o comportamento padrão. + +### Tópicos Avançados + +### Controlando o Multi-Tenancy + +Se sua solução for [multi-tenant](Multi-Tenancy.md), os tenants podem ter **bancos de dados separados**, você tem **múltiplas** classes `DbContext` em sua solução e algumas de suas classes `DbContext` devem ser utilizáveis **apenas do lado do host**, é recomendado adicionar o atributo `[IgnoreMultiTenancy]` em sua classe `DbContext`. Nesse caso, a ABP garante que o `DbContext` relacionado sempre usa a [connection string](Connection-Strings.md) do host, mesmo se você estiver em um tenant context. + +**Exemplo:** + +````csharp +[IgnoreMultiTenancy] +public class MyDbContext : AbpMongoDbContext +{ + ... +} +```` + +Não use o atributo `[IgnoreMultiTenancy]` se qualquer uma de suas entidades em seu `DbContext` puder ser persistida em um outro banco de dados de um tenant. + +> When you use repositories, ABP already uses the host database for the entities don't implement the `IMultiTenant` interface. So, most of time you don't need to `[IgnoreMultiTenancy]` attribute if you are using the repositories to work with the database. + +#### Definir Classes Repository Padrão + +Repositories genéricas padrão são implementadas pela classe `MongoDbRepository` por padrão. Você pode criar sua própria implementação e usá-la para implementação da repository padrão. + +Primeiro, defina suas classes de repository assim: + +```csharp +public class MyRepositoryBase + : MongoDbRepository + where TEntity : class, IEntity +{ + public MyRepositoryBase(IMongoDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } +} + +public class MyRepositoryBase + : MongoDbRepository + where TEntity : class, IEntity +{ + public MyRepositoryBase(IMongoDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } +} +``` + +O primeiro é para [entities com chaves compostas](Entities.md), o segundo é para entities com uma única chave primária. + +É sugerido herdar da classe `MongoDbRepository` e substituir os métodos, se necessário. Caso contrário, você terá que implementar todos os métodos de repository padrão manualmente. + +Agora, você pode usar a opção `SetDefaultRepositoryClasses`: + +```csharp +context.Services.AddMongoDbContext(options => +{ + options.SetDefaultRepositoryClasses( + typeof(MyRepositoryBase<,>), + typeof(MyRepositoryBase<>) + ); + // ... +}); +``` + +#### Definir classe base MongoDbContext ou Interface para Repositories padrão + +Se seu MongoDbContext herda de outro MongoDbContext ou implementa uma interface, você pode usar essa classe base ou interface como o MongoDbContext para repositories padrão. Exemplo: + +```csharp +public interface IBookStoreMongoDbContext : IAbpMongoDbContext +{ + Collection Books { get; } +} +``` + +`IBookStoreMongoDbContext` é implementado pela classe `BookStoreMongoDbContext`. Então você pode usar sobrecarga genérica do `AddDefaultRepositories`: + +```csharp +context.Services.AddMongoDbContext(options => +{ + options.AddDefaultRepositories(); + // ... +}); +``` + +Agora, seu `BookRepository` personalizado também pode usar a interface `IBookStoreMongoDbContext`: + +```csharp +public class BookRepository + : MongoDbRepository, + IBookRepository +{ + // ... +} +``` + +Uma vantagem de usar a interface para um MongoDbContext é que ela pode ser substituída por outra implementação. + +#### Substituir Outros DbContexts + +Depois de definir e usar adequadamente uma interface para um MongoDbContext, qualquer outra implementação pode usar as seguintes maneiras de substituí-lo: + +**ReplaceDbContextAttribute** + +```csharp +[ReplaceDbContext(typeof(IBookStoreMongoDbContext))] +public class OtherMongoDbContext : AbpMongoDbContext, IBookStoreMongoDbContext +{ + // ... +} +``` + +**Opção ReplaceDbContext** + +```csharp +context.Services.AddMongoDbContext(options => +{ + // ... + options.ReplaceDbContext(); +}); +``` + +Neste exemplo, `OtherMongoDbContext` implementa `IBookStoreMongoDbContext`. Este recurso permite que você tenha vários MongoDbContext (um por módulo) no desenvolvimento, mas um único MongoDbContext (implementa todas as interfaces de todos os MongoDbContexts) no tempo de execução. + +### Personalizar Operações em Massa + +Se você tiver uma lógica melhor ou usar uma biblioteca externa para operações em massa, pode substituir a lógica por meio da implementação de `IMongoDbBulkOperationProvider`. + +- Você pode usar o modelo de exemplo abaixo: + +```csharp +public class MyCustomMongoDbBulkOperationProvider + : IMongoDbBulkOperationProvider, ITransientDependency +{ + public async Task DeleteManyAsync( + IMongoDbRepository repository, + IEnumerable entities, + IClientSessionHandle sessionHandle, + bool autoSave, + CancellationToken cancellationToken) + where TEntity : class, IEntity + { + // Sua lógica aqui. + } + + public async Task InsertManyAsync( + IMongoDbRepository repository, + IEnumerable entities, + IClientSessionHandle sessionHandle, + bool autoSave, + CancellationToken cancellationToken) + where TEntity : class, IEntity + { + // Sua lógica aqui. + } + + public async Task UpdateManyAsync( + IMongoDbRepository repository, + IEnumerable entities, + IClientSessionHandle sessionHandle, + bool autoSave, + CancellationToken cancellationToken) + where TEntity : class, IEntity + { + // Sua lógica aqui. + } +} +``` + +## Veja Também + +* [Entities](Entities.md) +* [Repositories](Repositories.md) \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs index 3814ab96e3..5675bf1fd4 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentityUserRepository.cs @@ -56,6 +56,8 @@ namespace Volo.Abp.Identity int skipCount = 0, string filter = null, bool includeDetails = false, + Guid? roleId = null, + Guid? organizationUnitId = null, CancellationToken cancellationToken = default ); @@ -86,6 +88,8 @@ namespace Volo.Abp.Identity Task GetCountAsync( string filter = null, + Guid? roleId = null, + Guid? organizationUnitId = null, CancellationToken cancellationToken = default ); } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserRepositoryExternalUserLookupServiceProvider.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserRepositoryExternalUserLookupServiceProvider.cs index c0fb15d80c..40b4575afe 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserRepositoryExternalUserLookupServiceProvider.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserRepositoryExternalUserLookupServiceProvider.cs @@ -71,7 +71,7 @@ namespace Volo.Abp.Identity string filter = null, CancellationToken cancellationToken = new CancellationToken()) { - return await UserRepository.GetCountAsync(filter, cancellationToken); + return await UserRepository.GetCountAsync(filter, cancellationToken: cancellationToken); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs index dfed75c804..b463cd6497 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityUserRepository.cs @@ -136,6 +136,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore int skipCount = 0, string filter = null, bool includeDetails = false, + Guid? roleId = null, + Guid? organizationUnitId = null, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) @@ -149,6 +151,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore (u.Surname != null && u.Surname.Contains(filter)) || (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) ) + .WhereIf(roleId.HasValue, identityUser => identityUser.Roles.Any(x => x.RoleId == roleId.Value)) + .WhereIf(organizationUnitId.HasValue, identityUser => identityUser.OrganizationUnits.Any(x => x.OrganizationUnitId == organizationUnitId.Value)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityUser.UserName) : sorting) .PageBy(skipCount, maxResultCount) .ToListAsync(GetCancellationToken(cancellationToken)); @@ -186,6 +190,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public virtual async Task GetCountAsync( string filter = null, + Guid? roleId = null, + Guid? organizationUnitId = null, CancellationToken cancellationToken = default) { return await (await GetDbSetAsync()) @@ -198,6 +204,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore (u.Surname != null && u.Surname.Contains(filter)) || (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) ) + .WhereIf(roleId.HasValue, identityUser => identityUser.Roles.Any(x => x.RoleId == roleId.Value)) + .WhereIf(organizationUnitId.HasValue, identityUser => identityUser.OrganizationUnits.Any(x => x.OrganizationUnitId == organizationUnitId.Value)) .LongCountAsync(GetCancellationToken(cancellationToken)); } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs index 82db48b3ed..83181a6af8 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityUserRepository.cs @@ -138,6 +138,8 @@ namespace Volo.Abp.Identity.MongoDB int skipCount = 0, string filter = null, bool includeDetails = false, + Guid? roleId = null, + Guid? organizationUnitId = null, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) @@ -150,6 +152,8 @@ namespace Volo.Abp.Identity.MongoDB (u.Surname != null && u.Surname.Contains(filter)) || (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) ) + .WhereIf>(roleId.HasValue, identityUser => identityUser.Roles.Any(x => x.RoleId == roleId.Value)) + .WhereIf>(organizationUnitId.HasValue, identityUser => identityUser.OrganizationUnits.Any(x => x.OrganizationUnitId == organizationUnitId.Value)) .OrderBy(sorting.IsNullOrWhiteSpace() ? nameof(IdentityUser.UserName) : sorting) .As>() .PageBy>(skipCount, maxResultCount) @@ -195,6 +199,8 @@ namespace Volo.Abp.Identity.MongoDB public virtual async Task GetCountAsync( string filter = null, + Guid? roleId = null, + Guid? organizationUnitId = null, CancellationToken cancellationToken = default) { return await (await GetMongoQueryableAsync(cancellationToken)) @@ -207,6 +213,8 @@ namespace Volo.Abp.Identity.MongoDB (u.Surname != null && u.Surname.Contains(filter)) || (u.PhoneNumber != null && u.PhoneNumber.Contains(filter)) ) + .WhereIf>(roleId.HasValue, identityUser => identityUser.Roles.Any(x => x.RoleId == roleId.Value)) + .WhereIf>(organizationUnitId.HasValue, identityUser => identityUser.OrganizationUnits.Any(x => x.OrganizationUnitId == organizationUnitId.Value)) .LongCountAsync(GetCancellationToken(cancellationToken)); } diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs index 9f736c7e98..9f5fd42006 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs @@ -158,6 +158,7 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host Configure(options => { + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); @@ -172,6 +173,8 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Host options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); + options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch")); + options.Languages.Add(new LanguageInfo("es", "es", "Español")); }); Configure(options => diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs index ef1c345dc3..07727fef1d 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs @@ -93,6 +93,7 @@ namespace MyCompanyName.MyProjectName Configure(options => { + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); @@ -107,6 +108,8 @@ namespace MyCompanyName.MyProjectName options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); + options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch")); + options.Languages.Add(new LanguageInfo("es", "es", "Español")); }); context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs index 6733fcecae..a85600940b 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.IdentityServer/MyProjectNameIdentityServerModule.cs @@ -103,6 +103,7 @@ namespace MyCompanyName.MyProjectName Configure(options => { + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); @@ -117,6 +118,8 @@ namespace MyCompanyName.MyProjectName options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); + options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch")); + options.Languages.Add(new LanguageInfo("es", "es", "Español"s)); }); Configure(options => diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs index 035a1fe753..da2f87c79a 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs @@ -100,6 +100,7 @@ namespace MyCompanyName.MyProjectName Configure(options => { + options.Languages.Add(new LanguageInfo("ar", "ar", "العربية")); options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština")); options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)")); @@ -114,6 +115,8 @@ namespace MyCompanyName.MyProjectName options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文")); + options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch")); + options.Languages.Add(new LanguageInfo("es", "es", "Español")); }); Configure(options =>