Skip to content

Your First Mapping

quyvu edited this page Oct 13, 2026 · 2 revisions

Your First Mapping

A complete step-by-step guide to creating your first data mapping with FxMap, from defining models to executing the mapping with FluentAPI.

1

Define Your Entity

Start with a simple entity that holds the data you want to expose:

public class User
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string PhoneNumber { get; set; }
    public string ProvinceId { get; set; }
}

2

Define a Distributed Key

A distributed key is the shared contract between the entity config and the DTO profile:

public sealed class UserDistributedKey : IDistributedKey;

3

Configure the Entity

Use EntityConfigureOf<T> to describe what data is exposed:

public class UserConfig : EntityConfigureOf<User>
{
    protected override void Configure()
    {
        Id(x => x.Id);
        DefaultProperty(x => x.Name);
        UseDistributedKey<UserDistributedKey>();
        ExposedName(x => x.Email, "UserEmail");
    }
}

What this does: Links UserDistributedKey to the User entity, using Id as the lookup key and Name as the default property. Also exposes Email under the alias "UserEmail".

4

Create a Profile for Your DTO

Use ProfileOf<T> to declare which properties to auto-populate and from which source:

public class OrderResponseProfile : ProfileOf<OrderResponse>
{
    protected override void Configure()
    {
        UseDistributedKey<UserDistributedKey>()
            // UserId on the DTO is the lookup key
            .Of(x => x.UserId)
            // UserName ← User.Name (DefaultProperty)
            .For(x => x.UserName)
            // UserEmail ← User.Email (via ExposedName alias)
            .For(x => x.UserEmail, "UserEmail")
            // UserPhone ← User.PhoneNumber
            .For(x => x.UserPhone, "PhoneNumber");
    }
}

How it works: FxMap reads UserId from the DTO, looks up the User entity linked to UserDistributedKey, then populates UserName, UserEmail, and UserPhone automatically.

5

Use IDistributedMapper

Inject IDistributedMapper into your service and call MapDataAsync:

public class OrderService
{
    private readonly IDistributedMapper _mapper;
    private readonly IOrderRepository _orderRepository;
 
    public OrderService(IDistributedMapper mapper, IOrderRepository orderRepository)
    {
        _mapper = mapper;
        _orderRepository = orderRepository;
    }
 
    public async Task<OrderResponse> GetOrderAsync(string orderId)
    {
        var order = await _orderRepository.GetByIdAsync(orderId);
 
        var response = new OrderResponse
        {
            Id = order.Id,
            UserId = order.UserId
        };
 
        // FxMap auto-populates UserName, UserEmail, UserPhone
        await _mapper.MapDataAsync(response);
 
        return response;
    }
}

Complete Example

// 1. Entity
public class User
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string PhoneNumber { get; set; }
}
 
// 2. Distributed Key
public sealed class UserDistributedKey : IDistributedKey;
 
// 3. Entity Config (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");
    }
}
 
// 4. DTO
public class OrderResponse
{
    public string Id { get; set; }
    public string UserId { get; set; }
    public string UserName { get; set; }
    public string UserEmail { get; set; }
    public string UserPhone { get; set; }
}
 
// 5. Profile (consumer side)
public class OrderResponseProfile : ProfileOf<OrderResponse>
{
    protected override void Configure()
    {
        UseDistributedKey<UserDistributedKey>()
            .Of(x => x.UserId)
            .For(x => x.UserName)
            .For(x => x.UserEmail, "UserEmail")
            .For(x => x.UserPhone, "PhoneNumber");
    }
}
 
// 6. Use in service
public async Task<OrderResponse> GetOrderAsync(string orderId)
{
    var order = await _orderRepository.GetByIdAsync(orderId);
    var response = new OrderResponse { Id = order.Id, UserId = order.UserId };
 
    // Magic happens here!
    await _mapper.MapDataAsync(response);
 
    return response;
}

What Happens Behind the Scenes

1

Scan Profiles

FxMap scans the response object and finds all registered profiles that match its type.

2

Collect IDs

It gathers all the ID values (e.g., UserId) that need to be looked up.

3

Batch Fetch Data

FxMap makes efficient batch queries — all lookups for the same key are combined into a single request.

4

Map Properties

Using compiled expressions (10x faster than reflection), FxMap populates the declared properties.

Congratulations!

You've created your first FxMap mapping with zero boilerplate:

  • No manual data fetching logic
  • No manual property assignment
  • Automatic batch optimization
  • Type-safe FluentAPI configuration

Common Pitfalls

  • Register FxMap services in Program.cs using AddFxMap(...)
  • Register your EntityConfig classes with AddEntitiesFromAssemblyContaining<>()
  • Register your Profile classes with AddProfilesFromAssemblyContaining<>()
  • The .Of(x => x.UserId) property must exist and be populated before calling MapDataAsync
  • Remember to await MapDataAsync() — it is an async operation

Source: https://fxmapper.net/docs/first-mapping/ — the website is always the most up to date version.

Clone this wiki locally