docs/en/low-code/reference-entities.md
//[doc-seo]
{
"Description": "Link dynamic entities to existing C# entities like IdentityUser using Reference Entities in the ABP Low-Code System."
}
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 | 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 |
Dynamic entities defined via Attributes or model.json 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.
Reference entities make this possible by exposing existing entities for:
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.
Register reference entities in your Low-Code Initializer using AbpDynamicEntityConfig.ReferencedEntityList:
public static async Task InitializeAsync()
{
await Runner.RunAsync(async () =>
{
// Register reference entity with default display property only
AbpDynamicEntityConfig.ReferencedEntityList.Add<IdentityUser>(
"UserName"
);
// Register reference entity with additional exposed properties
AbpDynamicEntityConfig.ReferencedEntityList.Add<IdentityUser>(
"UserName", // Default display property
"UserName", // Exposed properties (for queries and display)
"Email",
"PhoneNumber"
);
// ... rest of initialization
await DynamicModelManager.Instance.InitializeAsync();
});
}
Add<TEntity> Methodpublic void Add<TEntity>(
string defaultDisplayProperty,
params string[] properties
) where TEntity : class, IEntity<Guid>
| Parameter | Description |
|---|---|
defaultDisplayProperty | Property name used as display value in lookups |
properties | Additional properties to expose (optional) |
The entity type must implement
IEntity<Guid>.
Reference a registered entity in a foreign key definition:
{
"name": "UserId",
"foreignKey": {
"entityName": "Volo.Abp.Identity.IdentityUser"
}
}
The entity name must match the CLR type's full name. The module automatically detects that this is a reference entity and uses the registered ReferenceEntityDescriptor.
Use the [DynamicForeignKey] attribute on a Guid property:
[DynamicEntity]
public class Customer
{
[DynamicForeignKey("Volo.Abp.Identity.IdentityUser", "UserName")]
public Guid? UserId { get; set; }
}
The ReferenceEntityDescriptor class stores metadata about the reference entity:
Name — Full CLR type nameType — The actual CLR typeDefaultDisplayPropertyName — Display property for lookupsProperties — List of ReferenceEntityPropertyDescriptor entriesWhen a foreign key points to a reference entity, the ForeignKeyDescriptor populates its ReferencedEntityDescriptor and ReferencedDisplayPropertyDescriptor instead of the standard EntityDescriptor fields.
Reference entities can be queried via the Scripting API:
// Query reference entity in interceptor or custom endpoint
var user = await db.get('Volo.Abp.Identity.IdentityUser', userId);
if (user) {
context.log('User: ' + user.UserName);
}
Guid primary keys (IEntity<Guid>).| Entity | Name for entityName | Typical Display Property |
|---|---|---|
| ABP Identity User | Volo.Abp.Identity.IdentityUser | UserName |