diff --git a/docs/en/low-code/fluent-api.md b/docs/en/low-code/fluent-api.md index ed91ea5a6d..de24871c3c 100644 --- a/docs/en/low-code/fluent-api.md +++ b/docs/en/low-code/fluent-api.md @@ -128,7 +128,7 @@ public Guid CustomerId { get; set; } | Parameter | Description | |-----------|-------------| -| `entityName` | Full name of the referenced entity (or [reference entity](reference-entities.md)) | +| `entityName` | Full name of the target entity — can be a **dynamic entity** (e.g., `"MyApp.Customers.Customer"`) or a **[reference entity](reference-entities.md)** (e.g., `"Volo.Abp.Identity.IdentityUser"`) | | `displayPropertyName` | Property to show in lookups | | `access` | `ForeignAccess.None`, `ForeignAccess.View`, or `ForeignAccess.Edit` (see [Foreign Access](foreign-access.md)) | diff --git a/docs/en/low-code/foreign-access.md b/docs/en/low-code/foreign-access.md index 79e9796750..aa9383f545 100644 --- a/docs/en/low-code/foreign-access.md +++ b/docs/en/low-code/foreign-access.md @@ -7,7 +7,9 @@ # Foreign Access -Foreign Access controls how related entities can be accessed through foreign key relationships. It determines whether users can view or manage related data directly from the referenced entity's UI. +Foreign Access controls how related **dynamic entities** can be accessed through foreign key relationships. It determines whether users can view or manage related data directly from the **target entity's** UI. + +> **Important:** Foreign Access only works between **dynamic entities**. It does not apply to [reference entities](reference-entities.md) because they are read-only and don't have UI pages. ## Access Levels @@ -15,9 +17,9 @@ The `ForeignAccess` enum defines three levels: | Level | Value | Description | |-------|-------|-------------| -| `None` | 0 | No access from the referenced entity side. The relationship exists only for lookups. | -| `View` | 1 | Read-only access. Users can view related records from the referenced entity's action menu. | -| `Edit` | 2 | Full CRUD access. Users can create, update, and delete related records from the referenced entity's action menu. | +| `None` | 0 | No access from the target entity side. The relationship exists only for lookups. | +| `View` | 1 | Read-only access. Users can view related records from the target entity's action menu. | +| `Edit` | 2 | Full CRUD access. Users can create, update, and delete related records from the target entity's action menu. | ## Configuring with Attributes @@ -104,15 +106,15 @@ Set the `access` field on a foreign key property: ## UI Behavior -When foreign access is configured: +When foreign access is configured between two **dynamic entities**: ### `ForeignAccess.View` -An **action menu item** appears on the referenced entity's data grid row (e.g., a "Visited Countries" item on the Country row). Clicking it opens a read-only modal showing related records. +An **action menu item** appears on the target entity's data grid row (e.g., a "Visited Countries" item on the Country row). Clicking it opens a read-only modal showing related records. ### `ForeignAccess.Edit` -An **action menu item** appears on the referenced entity's data grid row (e.g., an "Orders" item on the Customer row). Clicking it opens a fully functional CRUD modal where users can create, edit, and delete related records. +An **action menu item** appears on the target entity's data grid row (e.g., an "Orders" item on the Customer row). Clicking it opens a fully functional CRUD modal where users can create, edit, and delete related records. ### `ForeignAccess.None` @@ -120,19 +122,21 @@ No action menu item is added. The foreign key exists only for data integrity and ## Permission Control -Foreign access actions respect the **entity permissions** of the related entity. For example, if a user does not have the `Delete` permission for `Order`, the delete button will not appear in the foreign access modal, even if the access level is `Edit`. +Foreign access actions respect the **entity permissions** of the source entity (the entity with the foreign key). For example, if a user does not have the `Delete` permission for `Order`, the delete button will not appear in the foreign access modal, even if the access level is `Edit`. ## How It Works The `ForeignAccessRelation` class stores the relationship metadata: -* Source entity (the entity with the foreign key) -* Target entity (the referenced entity) -* Foreign key property name -* Access level +* **Source entity** — the dynamic entity with the foreign key (e.g., `Order`) +* **Target entity** — the dynamic entity being referenced (e.g., `Customer`) +* **Foreign key property** — the property name (e.g., `CustomerId`) +* **Access level** — `None`, `View`, or `Edit` The `DynamicEntityAppService` checks these relations when building entity actions and filtering data. +> **Terminology:** In foreign access context, "target entity" refers to the entity whose UI shows the action menu (the entity being pointed to by the foreign key). This is different from "reference entity" which specifically means an existing C# entity registered for read-only access. + ## See Also * [model.json Structure](model-json.md) diff --git a/docs/en/low-code/index.md b/docs/en/low-code/index.md index da55753ecd..9d1fcd91c3 100644 --- a/docs/en/low-code/index.md +++ b/docs/en/low-code/index.md @@ -238,14 +238,14 @@ See [model.json Structure](model-json.md) for the full specification. | Feature | Description | Documentation | |---------|-------------|---------------| -| **Attributes & Fluent API** | Define entities with C# attributes and configure programmatically | [Fluent API & Attributes](fluent-api.md) | -| **model.json** | Declarative entity definitions in JSON | [model.json Structure](model-json.md) | -| **Reference Entities** | Link to existing entities like `IdentityUser` | [Reference Entities](reference-entities.md) | +| **Attributes & Fluent API** | Define dynamic entities with C# attributes and configure programmatically | [Fluent API & Attributes](fluent-api.md) | +| **model.json** | Declarative dynamic entity definitions in JSON | [model.json Structure](model-json.md) | +| **Reference Entities** | Read-only access to existing C# entities (e.g., `IdentityUser`) for foreign key lookups | [Reference Entities](reference-entities.md) | | **Interceptors** | Pre/Post hooks for Create, Update, Delete with JavaScript | [Interceptors](interceptors.md) | | **Scripting API** | Server-side JavaScript for database queries and CRUD | [Scripting API](scripting-api.md) | | **Custom Endpoints** | REST APIs with JavaScript handlers | [Custom Endpoints](custom-endpoints.md) | -| **Foreign Access** | View/Edit related entities from the parent's UI | [Foreign Access](foreign-access.md) | -| **Export** | Export entity data to Excel (XLSX) or CSV | See below | +| **Foreign Access** | View/Edit related dynamic entities from the target entity's UI | [Foreign Access](foreign-access.md) | +| **Export** | Export dynamic entity data to Excel (XLSX) or CSV | See below | ## Export (Excel / CSV) diff --git a/docs/en/low-code/model-json.md b/docs/en/low-code/model-json.md index 13984c8710..a3ae4fbf74 100644 --- a/docs/en/low-code/model-json.md +++ b/docs/en/low-code/model-json.md @@ -185,10 +185,12 @@ Define a foreign key relationship inline on a property: | Attribute | Description | |-----------|-------------| -| `entityName` | **Required.** Full name of the referenced entity | +| `entityName` | **Required.** Full name of the target entity — can be a **dynamic entity** (e.g., `"LowCodeDemo.Customers.Customer"`) or a **[reference entity](reference-entities.md)** (e.g., `"Volo.Abp.Identity.IdentityUser"`) | | `displayPropertyName` | Property to display in lookups (defaults to entity's `displayProperty`) | | `access` | [Foreign access](foreign-access.md) level: `"none"`, `"view"`, or `"edit"` | +> **Note:** [Reference entities](reference-entities.md) are existing C# entities (like ABP's `IdentityUser`) that are registered for read-only access. Unlike dynamic entities, they don't get CRUD pages — they're used only for foreign key lookups and display values. + ### Validators Add validation rules to properties: diff --git a/docs/en/low-code/reference-entities.md b/docs/en/low-code/reference-entities.md index 717189c207..85f13395a1 100644 --- a/docs/en/low-code/reference-entities.md +++ b/docs/en/low-code/reference-entities.md @@ -7,35 +7,56 @@ # Reference Entities -Reference Entities allow you to create foreign key relationships from dynamic entities to **existing (static) C# entities** that are already defined in your application or in ABP modules. +Reference Entities allow you to create foreign key relationships from **dynamic entities** to **existing C# entities** that live outside the Low-Code System. + +## Dynamic Entities vs Reference Entities + +| | Dynamic Entities | Reference Entities | +|---|-----------------|-------------------| +| **Definition** | Defined via `[DynamicEntity]` attribute or `model.json` | Existing C# classes (e.g., `IdentityUser`, `Tenant`) | +| **CRUD Operations** | Full CRUD (Create, Read, Update, Delete) | **Read-only** — no create/update/delete | +| **UI Pages** | Auto-generated pages with data grids and forms | No UI pages | +| **Permissions** | Auto-generated permissions | No permissions | +| **Purpose** | Primary data management | Foreign key lookups and display values | +| **Registration** | `AbpDynamicEntityConfig.SourceAssemblies` | `AbpDynamicEntityConfig.ReferencedEntityList` | ## Overview -Dynamic entities defined via [Attributes](fluent-api.md) or [model.json](model-json.md) normally reference other dynamic entities. However, you may need to link to entities like ABP's `IdentityUser`, `Tenant`, or your own C# entity classes. Reference entities make this possible. +Dynamic entities defined via [Attributes](fluent-api.md) or [model.json](model-json.md) can reference **other dynamic entities** using foreign keys. However, you may also need to link to entities that exist **outside** the Low-Code System — such as ABP's `IdentityUser`, `Tenant`, or your own C# entity classes. -Unlike dynamic entities, reference entities are **read-only** from the Low-Code System's perspective — they don't get CRUD pages or APIs. They are used solely for: +**Reference entities** make this possible by exposing existing entities for: * **Foreign key lookups** — dropdown selection in UI forms -* **Display values** — showing the referenced entity's display property in grids -* **Query support** — querying via the [Scripting API](scripting-api.md) +* **Display values** — showing the entity's display property in grids instead of raw GUIDs +* **Read-only queries** — querying via the [Scripting API](scripting-api.md) + +> **Key distinction:** When you define a foreign key with `entityName`, the system checks if it's a registered **reference entity** first. If not found, it assumes it's a **dynamic entity**. ## Registering Reference Entities -Register reference entities in your Domain module's `ConfigureServices` using `AbpDynamicEntityConfig.ReferencedEntityList`: +Register reference entities in your [Low-Code Initializer](index.md#1-create-a-low-code-initializer) using `AbpDynamicEntityConfig.ReferencedEntityList`: ````csharp -public override void ConfigureServices(ServiceConfigurationContext context) +public static async Task InitializeAsync() { - AbpDynamicEntityConfig.ReferencedEntityList.Add( - "UserName" // Default display property - ); - - AbpDynamicEntityConfig.ReferencedEntityList.Add( - "UserName", // Default display property - "UserName", // Exposed properties - "Email", - "PhoneNumber" - ); + await Runner.RunAsync(async () => + { + // Register reference entity with default display property only + AbpDynamicEntityConfig.ReferencedEntityList.Add( + "UserName" + ); + + // Register reference entity with additional exposed properties + AbpDynamicEntityConfig.ReferencedEntityList.Add( + "UserName", // Default display property + "UserName", // Exposed properties (for queries and display) + "Email", + "PhoneNumber" + ); + + // ... rest of initialization + await DynamicModelManager.Instance.InitializeAsync(); + }); } ```` diff --git a/docs/en/low-code/scripting-api.md b/docs/en/low-code/scripting-api.md index 5b5b7de9ef..63b40c1f0c 100644 --- a/docs/en/low-code/scripting-api.md +++ b/docs/en/low-code/scripting-api.md @@ -282,6 +282,8 @@ Direct CRUD methods on the `db` object: | `db.update(entityName, entity)` | Update existing | `Promise` | | `db.delete(entityName, id)` | Delete by ID | `Promise` | +> **Note:** The `entityName` parameter can be either a **dynamic entity** (e.g., `"LowCodeDemo.Products.Product"`) or a **[reference entity](reference-entities.md)** (e.g., `"Volo.Abp.Identity.IdentityUser"`). However, `insert`, `update`, and `delete` operations only work on dynamic entities — reference entities are read-only. + ```javascript // Get by ID var product = await db.get('LowCodeDemo.Products.Product', id);