Browse Source

Docs: use DynamicEntityBase and async init

Update low-code documentation examples to reflect API changes: make entity classes inherit DynamicEntityBase across examples, remove the separate "Register the Assembly" step and renumber steps, and introduce an async low-code initializer (MyAppLowCodeInitializer) using AsyncOneTimeRunner and DynamicModelManager.Instance.InitializeAsync. Also adjust command/query examples: CustomProductCreateCommand now derives from CreateCommand<Product> and returns Guid, and a CustomQuery (Single) example was added. These edits align docs with the new initialization flow and base entity type.
pull/25021/head
SALİH ÖZKARA 1 month ago
parent
commit
00b93df5e8
  1. 83
      docs/en/low-code/fluent-api.md
  2. 24
      docs/en/low-code/index.md

83
docs/en/low-code/fluent-api.md

@ -16,7 +16,7 @@ C# Attributes and the Fluent API are the **recommended way** to define dynamic e
````csharp
[DynamicEntity]
[DynamicEntityUI(PageTitle = "Products")]
public class Product
public class Product : DynamicEntityBase
{
[DynamicPropertyUnique]
public string Name { get; set; }
@ -30,18 +30,7 @@ public class Product
}
````
### Step 2: Register the Assembly
````csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
AbpDynamicEntityConfig.SourceAssemblies.Add(
new DynamicEntityAssemblyInfo(typeof(YourDomainModule).Assembly)
);
}
````
### Step 3: Add Migration and Run
### Step 2: Add Migration and Run
```bash
dotnet ef migrations add Added_Product
@ -50,12 +39,12 @@ dotnet ef database update
You now have a complete Product management page with data grid, create/edit modals, search, sorting, and pagination.
### Step 4: Add Relationships
### Step 3: Add Relationships
````csharp
[DynamicEntity]
[DynamicEntityUI(PageTitle = "Orders")]
public class Order
public class Order : DynamicEntityBase
{
[DynamicForeignKey("MyApp.Customers.Customer", "Name", ForeignAccess.Edit)]
public Guid CustomerId { get; set; }
@ -65,7 +54,7 @@ public class Order
}
[DynamicEntity(Parent = "MyApp.Orders.Order")]
public class OrderLine
public class OrderLine : DynamicEntityBase
{
[DynamicForeignKey("MyApp.Products.Product", "Name")]
public Guid ProductId { get; set; }
@ -97,7 +86,7 @@ Marks a class as a dynamic entity. The entity name is derived from the class nam
````csharp
[DynamicEntity]
public class Product
public class Product : DynamicEntityBase
{
public string Name { get; set; }
public decimal Price { get; set; }
@ -108,7 +97,7 @@ Use the `Parent` property for parent-child (master-detail) relationships:
````csharp
[DynamicEntity(Parent = "MyApp.Orders.Order")]
public class OrderLine
public class OrderLine : DynamicEntityBase
{
public Guid ProductId { get; set; }
public int Quantity { get; set; }
@ -122,7 +111,7 @@ Configures entity-level UI. Entities with `PageTitle` get a menu item and a dedi
````csharp
[DynamicEntity]
[DynamicEntityUI(PageTitle = "Product Management")]
public class Product
public class Product : DynamicEntityBase
{
// ...
}
@ -211,7 +200,7 @@ Defines JavaScript interceptors on a class for CRUD lifecycle hooks:
InterceptorType.Post,
"context.log('Deleted: ' + context.commandArgs.entityId);"
)]
public class Organization
public class Organization : DynamicEntityBase
{
public string Name { get; set; }
}
@ -241,7 +230,7 @@ Reference in an entity:
````csharp
[DynamicEntity]
[DynamicEntityUI(PageTitle = "Organizations")]
public class Organization
public class Organization : DynamicEntityBase
{
public string Name { get; set; }
public OrganizationType OrganizationType { get; set; }
@ -272,28 +261,38 @@ The Fluent API has the **highest priority** in the configuration system. Use `Ab
### Basic Usage
Configure in your Domain module's `ConfigureServices`:
Configure in your Low-Code Initializer (e.g. `MyAppLowCodeInitializer`):
````csharp
public override void ConfigureServices(ServiceConfigurationContext context)
public static class MyAppLowCodeInitializer
{
AbpDynamicEntityConfig.EntityConfigurations.Configure(
"MyApp.Products.Product",
entity =>
{
entity.DefaultDisplayPropertyName = "Name";
private static readonly AsyncOneTimeRunner Runner = new();
var priceProperty = entity.AddOrGetProperty("Price");
priceProperty.AsRequired();
priceProperty.UI = new EntityPropertyUIDescriptor
{
DisplayName = "Unit Price",
CreationFormAvailability = EntityPropertyUIFormAvailability.Available
};
public static async Task InitializeAsync()
{
await Runner.RunAsync(async () =>
{
AbpDynamicEntityConfig.EntityConfigurations.Configure(
"MyApp.Products.Product",
entity =>
{
entity.DefaultDisplayPropertyName = "Name";
var priceProperty = entity.AddOrGetProperty("Price");
priceProperty.AsRequired();
priceProperty.UI = new EntityPropertyUIDescriptor
{
DisplayName = "Unit Price",
CreationFormAvailability = EntityPropertyUIFormAvailability.Available
};
entity.AddOrGetProperty("InternalNotes").AsServerOnly();
}
);
entity.AddOrGetProperty("InternalNotes").AsServerOnly();
}
);
await DynamicModelManager.Instance.InitializeAsync();
});
}
}
````
@ -435,7 +434,7 @@ public enum OrderStatus
// Customer entity
[DynamicEntity]
[DynamicEntityUI(PageTitle = "Customers")]
public class Customer
public class Customer : DynamicEntityBase
{
[DynamicPropertyUnique]
public string Name { get; set; }
@ -453,7 +452,7 @@ public class Customer
// Product entity
[DynamicEntity]
[DynamicEntityUI(PageTitle = "Products")]
public class Product
public class Product : DynamicEntityBase
{
[DynamicPropertyUnique]
public string Name { get; set; }
@ -474,7 +473,7 @@ public class Product
}
}"
)]
public class Order
public class Order : DynamicEntityBase
{
[DynamicForeignKey("MyApp.Customers.Customer", "Name", ForeignAccess.Edit)]
public Guid CustomerId { get; set; }
@ -485,7 +484,7 @@ public class Order
}
[DynamicEntity(Parent = "MyApp.Orders.Order")]
public class OrderLine
public class OrderLine : DynamicEntityBase
{
[DynamicForeignKey("MyApp.Products.Product", "Name")]
public Guid ProductId { get; set; }

24
docs/en/low-code/index.md

@ -34,7 +34,7 @@ Traditionally, adding a new entity with full CRUD functionality to an ABP applic
````csharp
[DynamicEntity]
[DynamicEntityUI(PageTitle = "Products")]
public class Product
public class Product : DynamicEntityBase
{
[DynamicPropertyUnique]
public string Name { get; set; }
@ -158,7 +158,7 @@ protected override void OnModelCreating(ModelBuilder builder)
````csharp
[DynamicEntity]
[DynamicEntityUI(PageTitle = "Customers")]
public class Customer
public class Customer : DynamicEntityBase
{
public string Name { get; set; }
@ -188,7 +188,7 @@ Define entities as C# classes with attributes. You get compile-time checking, In
````csharp
[DynamicEntity]
[DynamicEntityUI(PageTitle = "Orders")]
public class Order
public class Order : DynamicEntityBase
{
[DynamicForeignKey("MyApp.Customers.Customer", "Name", ForeignAccess.Edit)]
public Guid CustomerId { get; set; }
@ -198,7 +198,7 @@ public class Order
}
[DynamicEntity(Parent = "MyApp.Orders.Order")]
public class OrderLine
public class OrderLine : DynamicEntityBase
{
[DynamicForeignKey("MyApp.Products.Product", "Name")]
public Guid ProductId { get; set; }
@ -276,9 +276,9 @@ Create a class that implements `ILcCommand<TResult>` and decorate it with `[Cust
````csharp
[CustomCommand("Create", "MyApp.Products.Product")]
public class CustomProductCreateCommand : LcCommandBase<DynamicEntityDto>
public class CustomProductCreateCommand : CreateCommand<Product>
{
public override async Task<DynamicEntityDto> ExecuteWithResultAsync(DynamicCommandArgs commandArgs)
public override async Task<Guid> ExecuteWithResultAsync(DynamicCommandArgs commandArgs)
{
// Your custom create logic here
// ...
@ -307,6 +307,18 @@ public class CustomProductListQuery : ILcQuery<DynamicQueryResult>
}
````
````csharp
[CustomQuery("Single", "MyApp.Products.Product")]
public class CustomProductListQuery : ILcQuery<DynamicEntityDto>
{
public async Task<DynamicEntityDto> ExecuteAsync(DynamicQueryArgs queryArgs)
{
// Your custom single query logic here
// ...
}
}
````
| Parameter | Description |
|-----------|-------------|
| `queryName` | The query to replace: `"List"` or `"Single"` |

Loading…
Cancel
Save