Skip to main content
Version: 0.43

Adding New Entities and Child Tables

This step shows how to add a brand-new entity (not just an extension of an existing one) and wire it up as a child table on the parent's details view. You will create a MembershipPayment entity that tracks all payments related to a Member, and surface those payments inline on the member details view.

This is the most common shape for "one-to-many" relationships in Shesha: a child entity with a foreign key back to the parent, and a child table on the parent's details view that supports inline editing.


Create the MembershipPayment Entity​

Open the backend/Shesha.Membership.sln solution in Visual Studio 2022.

1. Add the Entity Class​

  1. Navigate to Shesha.Membership.Domain > Domain.
  2. Right-click the folder and choose Add > Class.
  3. Name the class MembershipPayment.cs.

Example - The MembershipPayment entity:

using Abp.Domain.Entities.Auditing;
using Shesha.Domain.Attributes;
using System;

namespace Shesha.Membership.Domain.Domain
{
/// <summary>
/// A payment made by a Member towards their membership.
/// </summary>
[Entity(TypeShortAlias = "Mem.MembershipPayment")]
public class MembershipPayment : FullAuditedEntity<Guid>
{
/// <summary>
/// The Member who made the payment.
/// </summary>
public virtual Member Member { get; set; }

/// <summary>
/// The amount paid.
/// </summary>
public virtual double Amount { get; set; }

/// <summary>
/// The date the payment was made.
/// </summary>
public virtual DateTime? PaymentDate { get; set; }
}
}
Why FullAuditedEntity?

FullAuditedEntity<Guid> is an Abp base class that gives the entity a Guid primary key plus standard audit columns: CreatedBy, CreationTime, LastModifiedBy, LastModificationTime, IsDeleted, DeleterUserId, and DeletionTime. Use it whenever you need full audit history with soft-delete behaviour.

2. Create the Migration​

  1. Navigate to Shesha.Membership.Domain > Migrations.
  2. Right-click the folder and choose Add > Class.
  3. Name the class with a timestamp, for example M20231124090300.cs.

Example - Migration creating the Mem_MembershipPayments table:

using FluentMigrator;
using Shesha.FluentMigrator;
using System;

namespace Shesha.Membership.Domain.Migrations
{
[Migration(20231124090300)]
public class M20231124090300 : Migration
{
public override void Up()
{
Create.Table("Mem_MembershipPayments")
.WithIdAsGuid()
.WithFullAuditColumns()
.WithForeignKeyColumn("MemberId", "Core_Persons").Nullable()
.WithColumn("Amount").AsDouble().Nullable()
.WithColumn("PaymentDate").AsDateTime().Nullable();
}

public override void Down()
{
throw new NotImplementedException();
}
}
}
Shesha FluentMigrator helpers

WithIdAsGuid adds a Guid primary key. WithFullAuditColumns adds the audit columns that match FullAuditedEntity<Guid>. WithForeignKeyColumn creates a column and its foreign key in a single call. These helpers come from Shesha.FluentMigrator. For more options see the FluentMigrator docs.

  1. Start the application (Debug > Start Debugging or F5).
  2. The app opens on the Swagger page.
  3. Search for MembershipPayment in Swagger to see the auto-generated CRUD endpoints.

Image

See CRUD APIs for what each endpoint does and how to customise the generated set.


Wire the Child Table into the Details View​

Now surface the payments inline on the member's details view, with a filter so each member only sees their own payments.

1. Add a DataTable Context​

  1. Open the member-details form designer.
  2. Drag a DataTable Context (see the DataTable Context reference) onto the form, below the existing details panel.
  3. Set its Entity Type to the new MembershipPayment entity.

Image

2. Add a Panel and DataTable​

  1. Drag a Panel (see the Panel reference) onto the DataTable Context.
  2. Label the panel Member Payments.

Image

  1. Drag a DataTable (see the DataTable reference) onto the panel.
  2. Configure the columns:
TypeProperty NameCaptionCreate Component
CRUD OperationsN/A(leave empty)N/A
DataamountAmountNumber Field
DatapaymentDatePayment DateDate Field

Image

Image

  1. Click Save on the Configure Columns modal.

3. Enable Inline Editing​

Inline editing lets users add payments directly into the table without opening a separate dialog. See the inline editing how-to for the full flow.

Configure the DataTable:

SettingValue
Can add inlineYes

Form type to use: Configured on a DataTable inside a member-details (details view) form.

Example - New row initialiser that links each payment to the current member:

return {
member: form.data.id,
};

This sets the member foreign key on each new payment row to the currently displayed member.

4. Add Toolbar Components​

To make the table easier to use, drag the following onto the Member Payments panel header:

ComponentPurpose
Quick SearchFree-text filter across columns.
Table PagerPaging controls.
Table View SelectorSwitches between named filters.

Image

5. Filter Payments to the Current Member​

Select the Table View Selector and configure a filter that restricts the table to payments belonging to the current member:

Image

Save the filter and set the Table View Selector's Hidden property to true - users don't need to see it, but the filter still applies.

Image

  1. Save the form.

Test It​

  • From the main menu, navigate to the members-table and refresh.
  • Drill down into the details view of any member.
  • Add a Membership Payment using inline editing.

Image

Image


Next Step​

Continue with Custom APIs to build a custom app service that enforces business rules before activating a membership.