402 First entity: PhoneType - chempkovsky/CS82ANGULAR GitHub Wiki
According to the rules defined in the article 006 Development Process Cycle
We can start with any entity from the list: PhoneType or Enterprise
Let's start with PhoneType
- Step #1:
- Run Visual Studio and Open
rupbes.firstapp- solution- Right Click
rupbes.firstapp.Domain.csproj-project- Select
Add/New Folder-menu item - Name created folder
PhBk
- Select
- Right Click
PhBkof therupbes.firstapp.Domain.csproj-project - Select
Add/Class-menu item - In the dialog enter the name for the class
PhbkPhoneType.cs
- Click
Add-button
- Right Click
- Run Visual Studio and Open
- Step #2:
- Open
PhbkPhoneType.cs-file and modify the body of the class as it is shown on the slide
- Open
Click to show the PhbkPhoneType.cs file
using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Auditing;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
using Volo.Abp;
// using JetBrains.Annotations;
namespace rupbes.firstapp.Phbk
{
public class PhbkPhoneType : BasicAggregateRoot<int>, IMultiTenant, IHasConcurrencyStamp
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[Display(Description = "Row id", Name = "Phone Type Id", Prompt = "Enter Phone Type Id", ShortName = "Phone Type Id")]
[Required]
public override int Id { get; protected set; } = default!;
[StringLength(20, MinimumLength = 3, ErrorMessage = "Invalid")]
[Display(Description = "Name of the Phone Type", Name = "Phone Type Name", Prompt = "Enter Phone Type Name", ShortName = "Phone Type Name")]
[Required]
public string PhoneTypeName { get; protected set; } = default!;
[Display(Description = "Description of the Phone Type", Name = "Phone Type Description", Prompt = "Enter Phone Type Description", ShortName = "Phone Type Description")]
[StringLength(250, ErrorMessage = "Invalid")]
public string? PhoneTypeDesc { get; protected set; }
[DisableAuditing]
[Display(Description = "Concurrency Stamp", Name = "Concurrency Stamp", Prompt = "Enter Concurrency Stamp", ShortName = "Concurrency Stamp")]
[StringLength(40, MinimumLength = 0, ErrorMessage = "Invalid")]
[Required]
[ConcurrencyCheck]
public virtual string ConcurrencyStamp { get; set; } = default!;
[Display(Description = "Tenant id", Name = "Tenant Id", Prompt = "Enter Tenant Id", ShortName = "Tenant Id")]
public virtual Guid? TenantId { get; protected set; }
public PhbkPhoneType() : base()
{
ConcurrencyStamp = Guid.NewGuid().ToString("N");
}
public PhbkPhoneType(int id, string phoneTypeName, string? phoneTypeDesc) : base(id)
{
Check.NotNullOrWhiteSpace(phoneTypeName, nameof(PhoneTypeName));
PhoneTypeName = phoneTypeName;
PhoneTypeDesc = phoneTypeDesc;
ConcurrencyStamp = Guid.NewGuid().ToString("N");
}
public virtual void ChangeVals(string phoneTypeName, string? phoneTypeDesc, string concurrencyStamp)
{
Check.NotNullOrWhiteSpace(phoneTypeName, nameof(PhoneTypeName));
PhoneTypeName = phoneTypeName;
PhoneTypeDesc = phoneTypeDesc;
ConcurrencyStamp = concurrencyStamp;
}
}
}Click to show the project structure

-
Note #1: The created class inherits
BasicAggregateRoot<int>, (will be used byDistributed Event Bus) -
Note #2: The created class implements
IMultiTenant, IHasConcurrencyStamp -
Note #3: The created class redefines primary key property
public override int Id { get; protected set; } = default!;. Such a redundancy is required for code generators. Later you can remove this property with#if (!NOTMODELING) ... #endif -
Note #4: Some of the properties have
protected set -
Note #5: The created class has non empty constructor
public PhbkPhoneType(int id, string phoneTypeName, string? phoneTypeDesc) : base(id)to setprotectedproperties. (will be used byDistributed Event Bus) -
Note #6: The created class has special methods
ChangeVals(string phoneTypeName, string? phoneTypeDesc, string concurrencyStamp)to updateprotectedproperties. (will be used byDistributed Event Bus) -
Note #7: ChangeVals-method has a predefined name. Code generators will look for the
ChangeVals-method. Other names will be ignored. -
Note #8: All properties still have
Display-attribute. (Despite the fact that Abp has its own localization mechanism). Code generators will useDisplay-attribute. -
Note #9: The input params names of no empty constructor and
ChangeVals-method must be equals to the names of the properties. Only the first letter of the input parameter name should be lowercase. -
Note #10: This is not entirely correct to have a pair
IMultiTenantand[DatabaseGenerated(DatabaseGeneratedOption.None)] int Id, i.e. the primary key is of typeintand is notDatabaseGeneratedOption.Identity. But this is normal for showing restrictions related to MultiTenant. For instance what should we do with the unique keys defined for the database-table. A database per tenant is the only way to avoid inconsistencies.