Browse Source

Part-7 & 8 completed for mongodb.

pull/4864/head
Halil İbrahim Kalkan 6 years ago
parent
commit
c19e1cb8af
  1. 21
      docs/en/Tutorials/Part-6.md
  2. 73
      docs/en/Tutorials/Part-7.md
  3. 8
      docs/en/Tutorials/Part-8.md

21
docs/en/Tutorials/Part-6.md

@ -56,12 +56,11 @@ In the previous parts, we've used the ABP infrastructure to easily build some se
* Used the [CrudAppService](../Application-Services.md) base class instead of manually developing an application service for standard create, read, update and delete operations.
* Used [generic repositories](../Repositories.md) to completely automate the database layer.
* Used [conventional API controllers](../API/Auto-API-Controllers.md) instead of manually writing API controllers.
For the "Authors" part;
* We will **do most of the things manually** to show how you can do it in case of need.
* We will implement **Domain Driven Design (DDD) best practices**.
* We will **do some of the things manually** to show how you can do it in case of need.
* We will implement some **Domain Driven Design (DDD) best practices**.
> **The development will be done layer by layer to concentrate on an individual layer in one time. In a real project, you will develop your application feature by feature (vertical) as done in the previous parts. In this way, you will experience both approaches.**
@ -122,10 +121,10 @@ namespace Acme.BookStore.Authors
* `private set` for the `Name` property restricts to set this property from out of this class. There are two ways of setting the name (in both cases, we validate the name):
* In the constructor, while creating a new author.
* Using the `ChangeName` method to update the name later.
* The `constructor` and the `ChangeName` method is `internal` to force to use these methods only in the domain layer, using the `AuthorManager` that will be explained below.
* `Check` class is an ABP Framework utility class to help you while checking method arguments (it throws exception on an invalid case).
* The `constructor` and the `ChangeName` method is `internal` to force to use these methods only in the domain layer, using the `AuthorManager` that will be explained later.
* `Check` class is an ABP Framework utility class to help you while checking method arguments (it throws `ArgumentException` on an invalid case).
`AuthorConsts` is a simple class that is located under the `Authors` namespace of the `Acme.BookStore.Domain.Shared` project:
`AuthorConsts` is a simple class that is located under the `Authors` namespace (folder) of the `Acme.BookStore.Domain.Shared` project:
````csharp
namespace Acme.BookStore.Authors
@ -137,7 +136,7 @@ namespace Acme.BookStore.Authors
}
````
Created this class inside the `Acme.BookStore.Domain.Shared` project since we will re-use it on the Data Transfer Objects (DTOs) later.
Created this class inside the `Acme.BookStore.Domain.Shared` project since we will re-use it on the [Data Transfer Objects](../Data-Transfer-Objects.md) (DTOs) later.
## AuthorManager: The Domain Service
@ -203,9 +202,9 @@ namespace Acme.BookStore.Authors
* `AuthorManager` forces to create an author and change name of an author in a controlled way. The application layer (will be introduced later) will use these methods.
> **DDD tip**: Do not introduce domain service methods unless they are needed and they perform core business rules. For this case, we needed to this service to be able to force the unique name constraint.
> **DDD tip**: Do not introduce domain service methods unless they are really needed and perform some core business rules. For this case, we needed to this service to be able to force the unique name constraint.
Both methods checks if there is already an author with the given name and throws a special business exception, `AuthorAlreadyExistsException`, defined as shown below:
Both methods checks if there is already an author with the given name and throws a special business exception, `AuthorAlreadyExistsException`, defined in the `Acme.BookStore.Domain` project as shown below:
````csharp
using Volo.Abp;
@ -223,7 +222,7 @@ namespace Acme.BookStore.Authors
}
````
`BusinessException` is a special exception type that. It is a good way to throw domain related exceptions. It is automatically handled by the ABP Framework and can be easily localized. `WithData` method is used to provide additional data to the exception object that will later be used on the localization message or for some other purpose.
`BusinessException` is a special exception type. It is a good practice to throw domain related exceptions when needed. It is automatically handled by the ABP Framework and can be easily localized. `WithData(...)` method is used to provide additional data to the exception object that will later be used on the localization message or for some other purpose.
Open the `BookStoreDomainErrorCodes` in the `Acme.BookStore.Domain.Shared` project and change as shown below:
@ -247,7 +246,7 @@ Whenever you throw an `AuthorAlreadyExistsException`, the end use will see a nic
## IAuthorRepository
`AuthorManager` inject the `IAuthorRepository`, so we need to define it. Create this new interface in the `Authors` folder (namespace) of the `Acme.BookStore.Domain` project:
`AuthorManager` injects the `IAuthorRepository`, so we need to define it. Create this new interface in the `Authors` folder (namespace) of the `Acme.BookStore.Domain` project:
````charp
using System;

73
docs/en/Tutorials/Part-7.md

@ -54,10 +54,10 @@ This tutorials has multiple versions based on your **UI** and **Database** prefe
This part explains how to configure the database integration for the `Author` entity introduced in the previous part.
## DB Context
{{if DB=="EF"}}
## DB Context
Open the `BookStoreDbContext` in the `Acme.BookStore.EntityFrameworkCore` project and add the following `DbSet` property:
````csharp
@ -98,7 +98,13 @@ This will create a new migration class. Then run the `Update-Database` command t
{{else if DB=="Mongo"}}
*TODO: MongoDB part is being prepared...*
## DB Context
Open the `BookStoreMongoDbContext` in the `MongoDb` folder of the `Acme.BookStore.MongoDB` project and add the following property to the class:
````csharp
public IMongoCollection<Author> Authors => Collection<Author>();
````
{{end}}
@ -160,9 +166,68 @@ namespace Acme.BookStore.Authors
* `WhereIf` is a shortcut extension method of the ABP Framework. It adds the `Where` condition only if the first condition meets (it filters by name, only if the filter was provided). You could do the same yourself, but these type of shortcut methods makes our life easier.
* `sorting` can be a string like `Name`, `Name ASC` or `Name DESC`. It is possible by using the [System.Linq.Dynamic.Core](https://www.nuget.org/packages/System.Linq.Dynamic.Core) NuGet package.
> See the [EF Core Integration document](../Entity-Framework-Core.md) for more information on the EF Core based repositories.
{{else if DB=="Mongo"}}
*TODO: MongoDB part is being prepared...*
Create a new class, named `MongoDbAuthorRepository` inside the `Acme.BookStore.MongoDB` project (in the `Authors` folder) and paste the following code:
```csharp
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Collections.Generic;
using System.Threading.Tasks;
using Acme.BookStore.MongoDB;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
namespace Acme.BookStore.Authors
{
public class MongoDbAuthorRepository
: MongoDbRepository<BookStoreMongoDbContext, Author, Guid>,
IAuthorRepository
{
public MongoDbAuthorRepository(
IMongoDbContextProvider<BookStoreMongoDbContext> dbContextProvider
) : base(dbContextProvider)
{
}
public async Task<Author> FindByNameAsync(string name)
{
return await GetMongoQueryable()
.FirstOrDefaultAsync(author => author.Name == name);
}
public async Task<List<Author>> GetListAsync(
int skipCount,
int maxResultCount,
string sorting,
string filter = null)
{
return await GetMongoQueryable()
.WhereIf<Author, IMongoQueryable<Author>>(
!filter.IsNullOrWhiteSpace(),
author => author.Name.Contains(filter)
)
.OrderBy(sorting)
.As<IMongoQueryable<Author>>()
.Skip(skipCount)
.Take(maxResultCount)
.ToListAsync();
}
}
}
```
* Inherited from the `MongoDbAuthorRepository`, so it inherits the standard repository method implementations.
* `WhereIf` is a shortcut extension method of the ABP Framework. It adds the `Where` condition only if the first condition meets (it filters by name, only if the filter was provided). You could do the same yourself, but these type of shortcut methods makes our life easier.
* `sorting` can be a string like `Name`, `Name ASC` or `Name DESC`. It is possible by using the [System.Linq.Dynamic.Core](https://www.nuget.org/packages/System.Linq.Dynamic.Core) NuGet package.
> See the [MongoDB Integration document](../MongoDB.md) for more information on the MongoDB based repositories.
{{end}}

8
docs/en/Tutorials/Part-8.md

@ -86,7 +86,7 @@ namespace Acme.BookStore.Authors
* `PagedResultDto` is a pre-defined DTO class in the ABP Framework. It has an `Items` collection and a `TotalCount` property to return a paged result.
* Preferred to return an `AuthorDto` (for the newly created author) from the `CreateAsync` method, while it is not used by this application - just to show a different usage.
This interface is using the DTOs defined below.
This interface is using the DTOs defined below (create them for your project).
### AuthorDto
@ -174,7 +174,7 @@ namespace Acme.BookStore.Authors
}
````
We could share (re-use) the same DTO among the create and the update operations. While you can do it, we prefer to create different DTOs for these operations since we see they generally be different by the time. So, code duplication is reasonable here compared to a tightly coupled design.
> We could share (re-use) the same DTO among the create and the update operations. While you can do it, we prefer to create different DTOs for these operations since we see they generally be different by the time. So, code duplication is reasonable here compared to a tightly coupled design.
## AuthorAppService
@ -499,7 +499,8 @@ using Shouldly;
using Xunit;
namespace Acme.BookStore.Authors
{
{ {{if DB=="Mongo"}}
[Collection(BookStoreTestConsts.CollectionDefinitionName)]{{end}}
public class AuthorAppService_Tests : BookStoreApplicationTestBase
{
private readonly IAuthorAppService _authorAppService;
@ -527,6 +528,7 @@ namespace Acme.BookStore.Authors
result.TotalCount.ShouldBeGreaterThanOrEqualTo(1);
result.Items.ShouldContain(author => author.Name == "George Orwell");
result.Items.ShouldNotContain(author => author.Name == "Douglas Adams");
}
[Fact]

Loading…
Cancel
Save