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
      • Right Click PhBk of the rupbes.firstapp.Domain.csproj-project
      • Select Add/Class-menu item
      • In the dialog enter the name for the class
        • PhbkPhoneType.cs
      • Click Add-button
  • Step #2:
    • Open PhbkPhoneType.cs-file and modify the body of the class as it is shown on the slide
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

project structure

  • Note #1: The created class inherits BasicAggregateRoot<int>, (will be used by Distributed 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 set protected properties. (will be used by Distributed Event Bus)
  • Note #6: The created class has special methods ChangeVals(string phoneTypeName, string? phoneTypeDesc, string concurrencyStamp) to update protected properties. (will be used by Distributed 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 use Display-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 type int and is not DatabaseGeneratedOption.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.
⚠️ **GitHub.com Fallback** ⚠️