From a1df9bf5a5a0aa695b6ee88bddc2f93873295a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 22 Jan 2021 10:27:02 +0300 Subject: [PATCH 1/7] Use async queryable in startup templates. --- .../MongoDb/MongoDbMyProjectNameDbSchemaMigrator.cs | 8 +++----- .../EntityFrameworkCore/Samples/SampleRepositoryTests.cs | 2 +- .../MongoDb/Samples/SampleRepositoryTests.cs | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.MongoDB/MongoDb/MongoDbMyProjectNameDbSchemaMigrator.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.MongoDB/MongoDb/MongoDbMyProjectNameDbSchemaMigrator.cs index 395ff28b39..2a00826ba7 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.MongoDB/MongoDb/MongoDbMyProjectNameDbSchemaMigrator.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.MongoDB/MongoDb/MongoDbMyProjectNameDbSchemaMigrator.cs @@ -18,15 +18,15 @@ namespace MyCompanyName.MyProjectName.MongoDB _serviceProvider = serviceProvider; } - public Task MigrateAsync() + public async Task MigrateAsync() { var dbContexts = _serviceProvider.GetServices(); - var connectionStringResolver = _serviceProvider.GetService(); + var connectionStringResolver = _serviceProvider.GetRequiredService(); foreach (var dbContext in dbContexts) { var connectionString = - connectionStringResolver.Resolve( + await connectionStringResolver.ResolveAsync( ConnectionStringNameAttribute.GetConnStringName(dbContext.GetType())); var mongoUrl = new MongoUrl(connectionString); var databaseName = mongoUrl.DatabaseName; @@ -39,8 +39,6 @@ namespace MyCompanyName.MyProjectName.MongoDB (dbContext as AbpMongoDbContext)?.InitializeCollections(client.GetDatabase(databaseName)); } - - return Task.CompletedTask; } } } diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs index 15fd991d77..3fdaa28ea7 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.EntityFrameworkCore.Tests/EntityFrameworkCore/Samples/SampleRepositoryTests.cs @@ -33,7 +33,7 @@ namespace MyCompanyName.MyProjectName.EntityFrameworkCore.Samples await WithUnitOfWorkAsync(async () => { //Act - var adminUser = await _appUserRepository + var adminUser = await (await _appUserRepository.GetQueryableAsync()) .Where(u => u.UserName == "admin") .FirstOrDefaultAsync(); diff --git a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs index deee3b4b61..0c45d0a52e 100644 --- a/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs +++ b/templates/app/aspnet-core/test/MyCompanyName.MyProjectName.MongoDB.Tests/MongoDb/Samples/SampleRepositoryTests.cs @@ -32,8 +32,7 @@ namespace MyCompanyName.MyProjectName.MongoDB.Samples await WithUnitOfWorkAsync(async () => { //Act - var adminUser = await _appUserRepository - .GetMongoQueryable() + var adminUser = await (await _appUserRepository.GetMongoQueryableAsync()) .FirstOrDefaultAsync(u => u.UserName == "admin"); //Assert From 7505797a2752a9083663f0c4e79b123d98618eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 22 Jan 2021 10:28:55 +0300 Subject: [PATCH 2/7] Update MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj --- ...anyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj index 1d2226ee96..f13bcef4d1 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations/MyCompanyName.MyProjectName.EntityFrameworkCore.DbMigrations.csproj @@ -12,6 +12,7 @@ + From ddf0a9520e7f038523095841e871d7db47276002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 22 Jan 2021 10:45:35 +0300 Subject: [PATCH 3/7] Set PublishTrimmed to false for Blazor app. --- .../MyCompanyName.MyProjectName.Blazor.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj index 078cccd39b..96a8f791ee 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj @@ -4,6 +4,7 @@ net5.0 true false + false From 1b0f7c950a30cc431d5f061f9cfd17cf8e14fa33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 22 Jan 2021 11:07:41 +0300 Subject: [PATCH 4/7] ABP version 4.2 Migration Guide --- docs/en/Migration-Guides/Abp-4_2.md | 92 +++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 docs/en/Migration-Guides/Abp-4_2.md diff --git a/docs/en/Migration-Guides/Abp-4_2.md b/docs/en/Migration-Guides/Abp-4_2.md new file mode 100644 index 0000000000..15285a879a --- /dev/null +++ b/docs/en/Migration-Guides/Abp-4_2.md @@ -0,0 +1,92 @@ +# ABP version 4.2 Migration Guide + +This version has no breaking changes but there is an important change on the repositories that should be applied for your application for an important performance and scalability gain. + +## IRepository.GetQueryableAsync + +`IRepository` interface inherits `IQueryable`, so you can directly use the standard LINQ extension methods, like `Where`, `OrderBy`, `First`, `Sum`... etc. + +**Example: Using LINQ directly over the repository object** + +````csharp +public class BookAppService : ApplicationService, IBookAppService +{ + private readonly IRepository _bookRepository; + + public BookAppService(IRepository bookRepository) + { + _bookRepository = bookRepository; + } + + public async Task DoItInOldWayAsync() + { + //Apply any standard LINQ extension method + var query = _bookRepository + .Where(x => x.Price > 10) + .OrderBy(x => x.Name); + + //Execute the query asynchronously + var books = await AsyncExecuter.ToListAsync(query); + } +} +```` + +*See [the documentation](https://docs.abp.io/en/abp/4.2/Repositories#iqueryable-async-operations) if you wonder what is the `AsyncExecuter`.* + +**Beginning from the version 4.2, the recommended way is using `IRepository.GetQueryableAsync()` to obtain an `IQueryable`, then use the LINQ extension methods over it.** + +**Example: Using the new GetQueryableAsync method** + +````csharp +public async Task DoItInNewWayAsync() +{ + //Use GetQueryableAsync to obtain the IQueryable first + var queryable = await _bookRepository.GetQueryableAsync(); + + //Then apply any standard LINQ extension method + var query = queryable + .Where(x => x.Price > 10) + .OrderBy(x => x.Name); + + //Finally, execute the query asynchronously + var books = await AsyncExecuter.ToListAsync(query); +} +```` + +ABP may start a database transaction when you get an `IQueryable` (If current [Unit Of Work](https://docs.abp.io/en/abp/latest/Unit-Of-Work) is transactional). In this new way, it is possible to **start the database transaction in an asynchronous way**. Previously, we could not get the advantage of asynchronous while starting the transactions. + +> **The new way has a significant performance and scalability gain. The old usage (directly using LINQ over the repositories) will be removed in the next major version (5.0).** You have a lot of time for the change, but we recommend to immediately take the action since the old usage has a big **scalability problem**. + +#### About IRepository Async Extension Methods + +Using IRepository Async Extension Methods has no such a problem. The examples below are pretty fine: + +````csharp +var countAll = await _personRepository + .CountAsync(); + +var count = await _personRepository + .CountAsync(x => x.Name.StartsWith("A")); + +var book1984 = await _bookRepository + .FirstOrDefaultAsync(x => x.Name == "John"); +```` + +See the [repository documentation](https://docs.abp.io/en/abp/4.2/Repositories#iqueryable-async-operations) to understand the relation between `IQueryable` and asynchronous operations. + +## .NET Package Upgrades + +ABP uses the latest 5.0.* .NET packages. If your application is using 5.0.0 packages, you may get an error on build. We recommend to depend on the .NET packages like `5.0.*` in the `.csproj` files to use the latest patch versions. + +Example: + +````xml + +```` + +## Blazorise Library Upgrade + +If you are upgrading to 4.2, you also need also upgrade the following packages in your Blazor application; + +* `Blazorise.Bootstrap` to `0.9.3-preview6` +* `Blazorise.Icons.FontAwesome` to `0.9.3-preview6` \ No newline at end of file From d990b482a83d38d0a9cbeb1d647fc974da45ed0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 22 Jan 2021 11:28:55 +0300 Subject: [PATCH 5/7] Update Abp-4_2.md --- docs/en/Migration-Guides/Abp-4_2.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/en/Migration-Guides/Abp-4_2.md b/docs/en/Migration-Guides/Abp-4_2.md index 15285a879a..084ae24caa 100644 --- a/docs/en/Migration-Guides/Abp-4_2.md +++ b/docs/en/Migration-Guides/Abp-4_2.md @@ -57,6 +57,15 @@ ABP may start a database transaction when you get an `IQueryable` (If current [U > **The new way has a significant performance and scalability gain. The old usage (directly using LINQ over the repositories) will be removed in the next major version (5.0).** You have a lot of time for the change, but we recommend to immediately take the action since the old usage has a big **scalability problem**. +### Actions to Take + +* Use the repository's queryable feature as explained before. +* If you've overridden `CreateFilteredQuery` in a class derived from `CrudAppService`, you should override the `CreateFilteredQueryAsync` instead and remove the `CreateFilteredQuery` in your class. +* If you've overridden `WithDetails` in your custom repositories, remove it and override `WithDetailsAsync` instead. +* If you've used `DbContext` or `DbSet` properties in your custom repositories, use `GetDbContextAsync()` and `GetDbSetAsync()` methods instead of them. + +You can re-build your solution and check the `Obsolete` warnings to find some of the usages need to change. + #### About IRepository Async Extension Methods Using IRepository Async Extension Methods has no such a problem. The examples below are pretty fine: From 29cbcdd55bb3c5fb31c6646357f73f0591f77c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Fri, 22 Jan 2021 11:30:23 +0300 Subject: [PATCH 6/7] Update Index.md --- docs/en/Migration-Guides/Index.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/en/Migration-Guides/Index.md b/docs/en/Migration-Guides/Index.md index 5973ee0a0d..26fe825f50 100644 --- a/docs/en/Migration-Guides/Index.md +++ b/docs/en/Migration-Guides/Index.md @@ -1,5 +1,6 @@ # ABP Framework Migration Guides -* [3.3.x to 4.0 Migration Guide](Abp-4_0.md) -* [2.9.x to 3.0 Migration Guide](../UI/Angular/Migration-Guide-v3.md) +* [4.x to 4.2](Abp-4_2.md) +* [3.3.x to 4.0](Abp-4_0.md) +* [2.9.x to 3.0](../UI/Angular/Migration-Guide-v3.md) From a5e9c90188c2e5fdcf10d84f4351bfa6fdcc0d58 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 22 Jan 2021 17:51:57 +0800 Subject: [PATCH 7/7] Update Dependency-Injection.md --- docs/en/Dependency-Injection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/Dependency-Injection.md b/docs/en/Dependency-Injection.md index 335e829461..f94901ad84 100644 --- a/docs/en/Dependency-Injection.md +++ b/docs/en/Dependency-Injection.md @@ -1,6 +1,6 @@ # Dependency Injection -ABP's Dependency Injection system is developed based on Microsoft's [dependency injection extension](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection) library (Microsoft.Extensions.DependencyInjection nuget package). So, it's documentation is valid in ABP too. +ABP's Dependency Injection system is developed based on Microsoft's [dependency injection extension](https://medium.com/volosoft/asp-net-core-dependency-injection-best-practices-tips-tricks-c6e9c67f9d96) library (Microsoft.Extensions.DependencyInjection nuget package). So, it's documentation is valid in ABP too. > While ABP has no core dependency to any 3rd-party DI provider, it's required to use a provider that supports dynamic proxying and some other advanced features to make some ABP features properly work. Startup templates come with Autofac installed. See [Autofac integration](Autofac-Integration.md) document for more information.