Repository navigation
Configure Entities
Use FluentAPI to define entity configurations and DTO profiles — the core building blocks of FxMap.
A marker interface that identifies an entity group. Both the entity config and the DTO profile reference the same key to establish the mapping contract.
Defines which entity exposes which properties, and links it to a distributed key. Lives on the data-provider side.
Defines which properties on a DTO should be auto-populated, and from which distributed key. Lives on the consumer side.
You can reference distributed keys by string name instead of type for complete decoupling between services.
A distributed key is a simple marker interface — it acts as a shared contract between the entity config and the profile.
// Define one key per entity group
public sealed class UserDistributedKey : IDistributedKey;
public sealed class ProductDistributedKey : IDistributedKey;
public sealed class OrderDistributedKey : IDistributedKey;Tip: Both EntityConfigureOf<T> and ProfileOf<T> support two overloads — UseDistributedKey<TKey>() and UseDistributedKey(string key). Both sides must use the same overload with the same values for the mapping to work.
Inherit from EntityConfigureOf<T> and override Configure() to describe the entity:
public class UserConfig : EntityConfigureOf<User>
{
protected override void Configure()
{
// Primary key used for lookups
Id(x => x.Id);
// Default property returned when no expression is specified
DefaultProperty(x => x.Name);
// Link this entity to a distributed key
UseDistributedKey<UserDistributedKey>();
// Expose a property under a custom name
ExposedName(x => x.Email, "UserEmail");
}
}-
Id(x => x.Id) — the primary key property used for lookups
-
DefaultProperty(x => x.Name) — returned when no expression is specified in the profile
-
UseDistributedKey() — links this config to a distributed key (generic overload)
UseDistributedKey(string key) — same but uses a string key for full assembly decoupling, such asUserDistributedKeyor a dotted name likeMyApp.Keys.UserKey; both sides must use the same string -
ExposedName(x => x.Email, "UserEmail") — exposes a property under an alias for consumer use
Inherit from ProfileOf<T> to describe how to populate a DTO:
public class UserResponseProfile : ProfileOf<UserResponse>
{
protected override void Configure()
{
UseDistributedKey<UserDistributedKey>()
// Which property on the DTO holds the ID to look up
.Of(x => x.UserId)
// Map to Name (uses DefaultProperty from entity config)
.For(x => x.UserName)
// Map to Email using expression
.For(x => x.UserEmail, "Email")
// Navigation property
.For(x => x.CountryName, "Country.Name")
// Aggregation
.For(x => x.TotalSpent, "Orders:sum(Total)")
// Projection
.For(x => x.UserDetails, "{Id, Name, Address.City as CityName}");
}
}Both EntityConfigureOf<T> and ProfileOf<T> support two overloads of UseDistributedKey:
// EntityConfigureOf<T>
public class UserConfig : EntityConfigureOf<User>
{
protected override void Configure()
{
Id(x => x.Id);
DefaultProperty(x => x.Name);
UseDistributedKey<UserDistributedKey>(); // ✅ type-safe
}
}
// ProfileOf<T>
public class OrderResponseProfile : ProfileOf<OrderResponse>
{
protected override void Configure()
{
UseDistributedKey<UserDistributedKey>() // ✅ type-safe
.Of(x => x.UserId)
.For(x => x.UserName);
}
}// EntityConfigureOf<T>
public class UserConfig : EntityConfigureOf<User>
{
protected override void Configure()
{
Id(x => x.Id);
DefaultProperty(x => x.Name);
UseDistributedKey("UserDistributedKey"); // ✅ no type ref
}
}
// ProfileOf<T>
public class OrderResponseProfile : ProfileOf<OrderResponse>
{
protected override void Configure()
{
UseDistributedKey("UserDistributedKey") // ✅ no type ref
.Of(x => x.UserId)
.For(x => x.UserName);
}
}Important: The entity config and the consumer profile must use the same overload to communicate. If the entity config uses UseDistributedKey<TKey>(), the profile must also use the generic overload. If the entity config uses UseDistributedKey(string key), the profile must also use the string overload with the same key values.
A complete microservices setup with multiple entity configurations:
// Distributed keys
public sealed class UserDistributedKey : IDistributedKey;
public sealed class ProvinceDistributedKey : IDistributedKey;
public sealed class CountryDistributedKey : IDistributedKey;
// Entity configs (data-provider side)
public class UserConfig : EntityConfigureOf<User>
{
protected override void Configure()
{
Id(x => x.Id);
DefaultProperty(x => x.Name);
UseDistributedKey<UserDistributedKey>();
ExposedName(x => x.Email, "UserEmail");
}
}
public class ProvinceConfig : EntityConfigureOf<Province>
{
protected override void Configure()
{
Id(x => x.Id);
DefaultProperty(x => x.Name);
UseDistributedKey<ProvinceDistributedKey>();
}
}
public class CountryConfig : EntityConfigureOf<Country>
{
protected override void Configure()
{
Id(x => x.Id);
DefaultProperty(x => x.Name);
UseDistributedKey<CountryDistributedKey>();
}
}Create one IDistributedKey per logical entity. Multiple profiles can share the same key.
Keep entity configs close to your domain models. Keep profiles close to your DTOs. Register them by assembly using AddEntitiesFromAssemblyContaining<> and AddProfilesFromAssemblyContaining<>.
Declare distributed keys as sealed to prevent inheritance and improve performance.
After creating your configs and profiles, register them usingAddEntitiesFromAssemblyContaining<> andAddProfilesFromAssemblyContaining<>inside AddFxMap(...).
Source: https://fxmapper.net/docs/configure-entities/ — the website is always the most up to date version.
Introduction
Getting Started
Configuration
- Service Registration
- Entities & Profiles
- Handlers
- Pipelines
- Strongly Typed IDs
- Error Handling
- Retry Policy
- Supervisor
- Telemetry
- Kestrel (HTTP/2)
- Analyzers
Expressions
- Overview
- Property Access
- Filters, Sorting & Paging
- Functions
- Aggregations
- Projections
- Coalesce & Ternary
- GroupBy
Data Providers
Transports
Integrations
Quality
AI Assistants
Migration
Release Notes