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
PhBk
of 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 setprotected
properties. (will be used byDistributed Event Bus
) -
Note #6: The created class has special methods
ChangeVals(string phoneTypeName, string? phoneTypeDesc, string concurrencyStamp)
to updateprotected
properties. (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
IMultiTenant
and[DatabaseGenerated(DatabaseGeneratedOption.None)] int Id
, i.e. the primary key is of typeint
and 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.