@ -24,11 +24,13 @@ In this part, you will create a new entity named `Book` and generate CRUD pages
## Opening the ABP Suite
After creating our solution in the previous part, now we can open the ABP Suite and start generating CRUD pages. You can select the *ABP Suite -> Open* command on the main menu to open ABP Suite:
> Please **stop the application** in ABP Studio's *Solution Runner* panel, if it's currently running, because ABP Suite will make changes in the solution and it might need to build the solution in some steps and running the solution prevents to build it.
After creating the solution in the previous part, now you can open the ABP Suite and start generating CRUD pages. You can select the *ABP Suite -> Open* command on the main menu to open ABP Suite:

After clicking the related command, pre-integrated browser of ABP Studio should be opened, then we can start generating entities and all related codes with a few configurations:
After clicking the related command, pre-integrated browser of ABP Studio should open, then you can start generating entities and all related codes with a few configurations:

@ -45,7 +47,7 @@ ABP Suite sets:
* Primary key type as **Guid**,
* Plural name, database name, namespace, page title, menu item and more...
Let's change the menu-item value as **book** to show a proper icon in the generated UI, and also enable **code customization**, **creating unit & integration tests**, and other options as you wish:
You can change the menu-item value as **book** to show a proper icon in the generated UI, and also enable **code customization**, **creating unit & integration tests**, and other options as you wish:

@ -62,11 +64,11 @@ Here the details:
You can leave the other configurations as default.
> ABP Suite allows you to define properties with a great range of options, for example, you can specify the property type as *string*, *int*, *float*, *Guid*, *DateTime*, and even *File* (for file upload) and also you can set any options by building up your properties, such as specifying it as *required*, or *nullable*, setting *max-min length*, *default value* and more...
> ABP Suite allows you to define properties with a great range of options, for example, you can specify the property type as *string*, *int*, *float*, *Guid*, *DateTime*, and even *File* (for file upload) and also you can set any options while defining your properties, such as specifying it as *required*, or *nullable*, setting *max-min length*, *default value* and more...
While defining the properties, we defined a *Type* property with the type of *enum*. ABP Suite asks for an enum path to read the enum file, and set the namespace, and enum name in the generated code.
While defining the properties, you defined a *Type* property with the type of *enum*. ABP Suite asks for an enum path to read the enum file, and set the namespace, and enum name in the generated code.
For that purpose, we should create a `BookType` enum in the `Acme.BookStore.Domain.Shared` project under the **Books** folder as follows:
For that purpose, you should create a `BookType` enum in the `Acme.BookStore.Domain.Shared` project under the **Books** folder as follows:
```csharp
namespace Acme.BookStore.Books;
@ -89,11 +91,24 @@ Then, you can specify the enum path for the `Type` property in ABP Suite like in

> After you select the enum file, ABP Suite automatically sets the namespace and enum name, and lists your enum values in the next section. You can change these values, but for now, you can leave as is.
After that, you can click the **Save and Generate** button to start the code generation process:

ABP Suite will generate the necessary code for you. It will take some time to complete the process. After the process is completed, you will see a success message, you can click the *Ok* button, and build & start the application by clicking the *Run -> Build & Start* button in the *Solution Runner* panel:
ABP Suite will generate the necessary code for you. It generates:
* `Book` entity (also `BookBase` class, which is allow you customizing the generated entity),
* A new **migration** (and also applies to the database),
* All related **permission**, **object mapping** and **navigation menu item** configurations,
* and all required **UI components and pages**.
It will take some time to complete the process. After the process is completed, you will see a success message, you can click the *Ok* button, and build & start the application by clicking the *Run -> Build & Start* button in the *Solution Runner* panel:

@ -101,6 +116,8 @@ After the application is started, you can right-click and *Browse* on the applic

On this page, you can create a new book, update an existing book, delete a book, export all records (or the filtered records) to excel, filter the records by using the advanced filter section, bulk delete multiple records and so on.
## Summary
In this part, we've created a new entity named `Book` and generated the necessary code for it with [ABP Suite](../../suite/index.md) within a few clicks. ABP Suite generated the all code for us, including the **entity**, **application service**, **database relations**, **unit & integration tests**, **UI** and **defined the custom hooks for code customization**.
In this part, you've created a new entity named `Book` and generated the necessary code for it with [ABP Suite](../../suite/index.md) with a few clicks. ABP Suite generated the all code for you, including the **entity**, **application service**, **database relations**, **unit & integration tests**, **UI** and **defined the custom hooks for code customization**.
@ -32,7 +32,7 @@ Click the entity selection box in the top right of the *CRUD page generation* pa

Then, you can type `Author` for the *Name* field and leave the other options as is (you can change the menu icon as **pen**, if you wish). ABP Suite automatically calculates proper values for the rest of the inputs for you:
Then, you can type `Author` for the *Name* field and leave the other options as is (you can change the menu icon as **pen** for a proper menu icon, and/or other options, if you wish). ABP Suite automatically calculates proper values for the rest of the inputs for you:

@ -70,10 +70,10 @@ After the application is started, you can right-click and *Browse* on the applic

## Summary
As you can see, the *Name* field is **required**, the *Birth Date* field shows a datepicker, and the *Short Bio* field is also **required** and it's a **textarea**. You just configured how you want your properties with some options (for example, setting the short bio as **textarea** and **required**), and ABP Suite generated code according that.
In this part, we've created a new entity named `Author` and generated the necessary code for it with [ABP Suite](../../suite/index.md) within a few clicks. ABP Suite generated the all code for us, including the **entity**, **application service**, **database relations**, **unit & integration tests**, **UI** and **defined the custom hooks for code customization**.
## Summary
So far, we have created the `Book` (in the previous part) and `Author` entities (& generated code for all functionalities) for the book store application. However, currently there is no relation between these entities.
In this part, you've created a new entity named `Author` and generated the necessary code for it with [ABP Suite](../../suite/index.md) with a few clicks. ABP Suite generated the all code for you, including the **entity**, **application service**, **database relations**, **unit & integration tests**, **UI** and **defined the custom hooks for code customization**.
In the next part, we will establish [one-to-many relation](../../suite/generating-crud-page.md) between these two entities.
In the next part, you will establish [one-to-many relation](../../suite/generating-crud-page.md) between the`Book` and `Author` entities.
In the previous parts, we have created the `Book` and `Author` entities (& generated code for all functionalities) for the book store application. However, currently there is no relation between these entities.
In the previous parts, you have created the `Book` and `Author` entities (& generated code for all functionalities) for the book store application. However, currently there is no relation between these entities.
In this part, we will establish to **one-to-many relation** between the `Book` and `Author` entities.
In this part, you will establish to **one-to-many relation** between the `Book` and `Author` entities.
## Establishing Relations with ABP Suite
ABP Suite allows establishing both **one-to-many** and [many-to-many](../../suite/creating-many-to-many-relationship.md) relationships.
In this tutorial, we will only establish **one-to-many relation** between `Book` and `Author` entities. It's pretty straightforward to establish a relationship with ABP Suite. You should just need to navigate to the *Navigations* tab, and provide the metadata for navigation property (1-n) or navigation collection (n-n) relations.
In this tutorial, you will only establish **one-to-many relation** between `Book` and `Author` entities. It's pretty straightforward to establish a relationship with ABP Suite. You should just need to navigate to the *Navigations* tab, and provide the metadata for navigation property (1-n) or navigation collection (n-n) relations.
## Creating Book to Author Relationship
@ -38,7 +38,7 @@ To establish **one-to-many relations** between *Book* and *Author* entities, sel

Then, you can open the *Navigations* tab, and click the **Add navigation property (1-n)** button. After that, a navigation property model will be opened, and you can fill the inputs like in the following figure:
Then, you can open the *Navigations* tab, and click the **Add navigation property (1-n)** button. After that, a navigation property model will open, and you can fill the fields like in the following figure:

@ -46,8 +46,8 @@ Here is the details:
* Selected the entity as `Author`. (ABP Suite will establish one-to-many relation between *Book* and *Author* entities with this configuration)
* Set the property name as *AuthorId*, it will be set as foreign-key restriction in the database and all related database configurations will be made by ABP Suite.
* Selected the display property as *Name*, this will be used in the dropdown component, to set an author with a book.
* Also, made the relation **required** and also made it **filterable** so books can be filterable by authors.
* Selected the display property as *Name*, this will be used in the dropdown component to set an author with a book& also it will be shown in the datatable of the *Books* page.
* Also, made the relation **required** and set it **filterable** so books can be filterable by authors.
After, specifying the metadata, you can click the *Ok* button to close the modal. Then, click the **Save and generate** button to start code generation process. ABP Suite will establish one-to-many relationship between the entities, and will generate all necessary code automatically:
@ -57,16 +57,112 @@ It will take some time to complete the process. After the process is completed,

After the application is started, you can right-click and *Browse* on the application to open it in the ABP Studio's pre-integrated browser. You can first create an author and then create a book with the author:
After the application is started, you can right-click and *Browse* on the application to open it in the ABP Studio's pre-integrated browser. You can first create an author and then create a book with the author for testing:
Also, notice that, in the advanced filter section, there is an **Author** dropdown, which you can use to filter books by authors (remember we set **filterable** while defining navigation property and thanks to that, ABP Suite generated the code accordingly):
Also, notice that, in the advanced filter section, there is an **Author** dropdown, which you can use to filter books by authors (remember you set **filterable** while defining navigation property and thanks to that, ABP Suite generated the code accordingly):
> Test projects slightly differs based on your UI and Database selection. For example, if you select MongoDB, then the `Acme.BookStore.EntityFrameworkCore.Tests` will be `Acme.BookStore.MongoDB.Tests`.
ABP Suite generated unit & integration tests, for the `Book`&`Author` entities. If you open the **Test explorer** in your IDE, you will see the following tests are generated:

ABP Suite generated tests for repository implementations & application service implementations for the generated code, if you enable *Create unit & integration tests* option, while creating the entity. Since, you already did that in the previous parts, it generated the all required tests for the entities.
Let's examine one of the generated test classes. Open the *BooksAppServiceTests* (under the *test/Acme.BookStore.Application.Tests/Books/BookApplicationTests.cs*) and check the `CreateAsync` method:
```csharp
[Fact]
public async Task CreateAsync()
{
// Arrange
var input = new BookCreateDto
{
Name = "6c3d1eda8bf04852b7bd5dfdbbd93224b252478c2e474d4c8faf24fa6b182168ca830d4f80e64e4a8e363f33e151d1d34a04be4709274c7fbf2214f9bb3a16c3",
* Create the `BookCreateDto` input DTO object, and fill its values with dummy data to simulate creating a book,
* Then, it calls the `IBooksAppService.CreateAsync` method to create a book,
* And finally, asserts the returned result to see if it's as expected or not.
Notice, also the *AuthorId* is set in the `BookCreateDto` object. At that point, you might ask yourself that I haven't created the author with that ID before, should not it throw exception?
No, it will not throw an exception, because ABP Suite also generates simple dummy data for the entities just for the tests! You can see the test data seed contributors under the *Acme.BookStore.Domain.Tests* project:

Here is the content of the `AuthorsDataSeedContributor.SeedAsync` method:
```csharp
public async Task SeedAsync(DataSeedContext context)
Since ABP Suite generated the test data seed contributors for each entity, you have initial data while testing your services. Also, as you would notice, the id in this example (*602460f6-df6e-456a-89d9-8c5870dfc583*) is same as the *authorId* field in the `BooksAppServiceTests.CreateAsync` method.
Let's execute all tests, and see the results:

## Summary
So far, we have created the all functionality for the bookstore application without needing to write any single line of code. ABP Suite generated the entities, application services, UI components, unit & integration tests and more...
So far, you have created the all functionality for the bookstore application without needing to write any single line of code. ABP Suite generated the entities, application services, UI components, unit & integration tests and more...
In the next part, we will write some code and modify the ABP Suite's generated code by writing the code in the specified hookpoints. Thanks to [ABP Suite's Customized Code Support](../../suite/customizing-the-generated-code.md), in the next generation, our custom code will not be overridden and will be preserved.
In the next part, you will write some code and modify the ABP Suite's generated code by writing the code in the specified hookpoints. Thanks to [ABP Suite's Customized Code Support](../../suite/customizing-the-generated-code.md), in the next generation, our custom code will not be overridden and will be preserved.