FxMap 4.1.1
dotnet add package FxMap --version 4.1.1
NuGet\Install-Package FxMap -Version 4.1.1
<PackageReference Include="FxMap" Version="4.1.1" />
<PackageVersion Include="FxMap" Version="4.1.1" />
<PackageReference Include="FxMap" />
paket add FxMap --version 4.1.1
#r "nuget: FxMap, 4.1.1"
#:package FxMap@4.1.1
#addin nuget:?package=FxMap&version=4.1.1
#tool nuget:?package=FxMap&version=4.1.1
<p align="center"> <img src="https://raw.githubusercontent.com/quyvu01/FxMap/main/FxMap.png" alt="FxMap" width="120" /> </p>
<h1 align="center">FxMap</h1>
<p align="center"> Distributed data mapping for .NET — declare where a property comes from, and FxMap fetches it from the service that owns the data, over the transport you already run. </p>
<p align="center"> <a href="https://www.nuget.org/packages/FxMap"><img alt="NuGet" src="https://img.shields.io/nuget/v/FxMap.svg" /></a> <a href="https://www.nuget.org/packages/FxMap"><img alt="Downloads" src="https://img.shields.io/nuget/dt/FxMap.svg" /></a> <a href="https://github.com/quyvu01/FxMap/actions/workflows/build.yml"><img alt="Build" src="https://github.com/quyvu01/FxMap/actions/workflows/build.yml/badge.svg" /></a> <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-blue.svg" /></a> <img alt=".NET" src="https://img.shields.io/badge/.NET-8%20%7C%209%20%7C%2010-512BD4.svg" /> </p>
<p align="center"> <a href="https://fxmapper.net"><b>Documentation</b></a> · <a href="https://fxmapper.net/docs/quick-start/"><b>Getting Started</b></a> · <a href="https://fxmapper.net/docs/expressions"><b>Expression Language</b></a> · <a href="https://discord.gg/XJNzPbqg7"><b>Discord</b></a> </p>
In a microservice system a response often carries only keys: an order has a UserId, a ProvinceId, a ProductId.
Showing it means collecting UserName, ProvinceName, ProductName from the services that own them, and writing
that glue again for every endpoint. FxMap turns the glue into a declaration:
public class OrderResponse
{
public string UserId { get; set; }
public string UserName { get; set; } // filled by FxMap
public string UserEmail { get; set; } // filled by FxMap
}
public class OrderResponseProfile : ProfileOf<OrderResponse>
{
protected override void Configure() =>
UseDistributedKey<UserDistributedKey>()
.Of(x => x.UserId)
.For(x => x.UserName)
.For(x => x.UserEmail, "Email");
}
await distributedMapper.MapDataAsync(response); // one batched request per key, however many objects
The service that owns the data registers an entity configuration and a data provider. FxMap batches the ids, sends them over a transport (or answers locally when the owner is the same service), and writes the results back. No client code per field, and no coupling between the two services beyond a key name.
Features
- FluentAPI mapping: declare the mapping with
ProfileOf<T>andEntityConfigureOf<T>; no attributes on your DTOs, and property access is compiled once per type. - Expression language: a SQL-like DSL for navigation, filters, aggregations, projections, indexers and conditions (
Orders(Status = 'Done'):sum(Total)). - Batched and chained: one request per distributed key and dependency level, with distinct ids, however many objects are mapped; chains such as
UserId → ProvinceId → CountryIdresolve level by level. - Data providers: Entity Framework Core and MongoDB.
- Transports: gRPC, NATS, RabbitMQ, Kafka, Azure Service Bus and Amazon SQS, with retries and supervision.
- GraphQL integration with HotChocolate.
- Compile-time checks: Roslyn analyzers for misconfigured profiles and entities.
- Observable: activities for OpenTelemetry tracing on mapping and data access.
- Targets .NET 8, 9 and 10.
All FxMap.* packages need to have the same version.
Quick Start
dotnet add package FxMap
// 1. Configure FxMap
builder.Services.AddFxMap(cfg =>
{
cfg.AddEntitiesFromAssemblyContaining<SomeEntityAssemblyMarker>();
cfg.AddProfilesFromAssemblyContaining<SomeProfileAssemblyMarker>();
});
// 2. Define a distributed key
public sealed class UserDistributedKey : IDistributedKey;
// 3. Configure the entity with FluentAPI
public class UserConfig : EntityConfigureOf<User>
{
protected override void Configure()
{
Id(x => x.Id);
DefaultProperty(x => x.Name);
UseDistributedKey<UserDistributedKey>(); // Or you want to absolute lose coupling, you can use: UseDistributedKey("UserDistributedKey")
ExposedName(x => x.Email, "UserEmail");
}
}
// 4. Define a profile for your DTO
public class UserResponseProfile : ProfileOf<UserResponse>
{
protected override void Configure()
{
UseDistributedKey<UserDistributedKey>() // Or you want to absolute lose coupling, you can use: UseDistributedKey("UserDistributedKey")
.Of(x => x.UserId)
.For(x => x.UserName)
.For(x => x.UserEmail, "Email");
}
}
Expression Examples
public class UserResponseProfile : ProfileOf<UserResponse>
{
protected override void Configure()
{
UseDistributedKey<UserDistributedKey>()
.Of(x => x.UserId)
// Simple property access
.For(x => x.UserEmail, "Email")
// Navigation properties
.For(x => x.CountryName, "Country.Name")
// Filtering
.For(x => x.CompletedOrders, "Orders(Status = 'Done')")
// Aggregation
.For(x => x.TotalSpent, "Orders:sum(Total)")
// Projection
.For(x => x.UserDetails, "{Id, Name, Address.City as CityName}")
// GroupBy
.For(x => x.OrdersByStatus, "Orders:groupBy(Status).{Status, :count as Count}");
}
}
For complete expression syntax including filters, indexers, functions, aggregations, boolean functions, coalesce, ternary operators, and more, visit Expression Documentation.
Packages
| Package | Description | .NET | Documentation |
|---|---|---|---|
| Core | |||
| FxMap | FxMap core: profiles, entity configs, the mapper and the expression language | 8.0, 9.0, 10.0 | fxmapper.net |
| Data providers | |||
| FxMap.EntityFrameworkCore | Answers requests from an Entity Framework Core DbContext |
8.0, 9.0, 10.0 | README |
| FxMap.MongoDb | Answers requests from MongoDB collections | 8.0, 9.0, 10.0 | README |
| Integrations | |||
| FxMap.HotChocolate | Fills GraphQL response types through HotChocolate | 8.0, 9.0, 10.0 | README |
| Transports | |||
| FxMap.Grpc | gRPC transport | 8.0, 9.0, 10.0 | README |
| FxMap.Nats | NATS transport | 8.0, 9.0, 10.0 | README |
| FxMap.RabbitMq | RabbitMQ transport | 8.0, 9.0, 10.0 | README |
| FxMap.Kafka | Apache Kafka transport | 8.0, 9.0, 10.0 | README |
| FxMap.Azure.ServiceBus | Azure Service Bus transport (Standard / Premium tiers) | 8.0, 9.0, 10.0 | README |
| FxMap.Aws.Sqs | Amazon SQS transport | 8.0, 9.0, 10.0 | README |
| Tooling | |||
| FxMap.Analyzers | Roslyn analyzer that validates expression strings at compile time | 8.0, 9.0, 10.0 | README |
Performance
FxMap is built to enrich data that lives in other services, so most of a real call is spent waiting on the network. This benchmark removes the network to measure only the mapper itself: FxMap enriches DTOs from an EF Core InMemory database in the same process (no transport), compared with AutoMapper 14 ProjectTo doing a single projected query.
Scenario: each order has a customer (customer → province → country) and 3-5 items (item → product → category). Both sides produce the same OrderDto graph (the benchmark checks that the results are identical).
- AutoMapper:
db.Orders.ProjectTo<OrderDto>(config), one query with joins. - FxMap: load the DTOs with only their scalar values and keys, then
IDistributedMapper.MapDataAsync(dtos)resolves customer, province, country, product and category throughProfileOf<T>and the EF Core data provider.
| Orders | AutoMapper ProjectTo |
FxMap (query + enrich) | FxMap time vs AutoMapper | FxMap memory vs AutoMapper |
|---|---|---|---|---|
| 10 | 164 µs / 276 KB | 277 µs / 382 KB | 1.69× | 1.38× |
| 100 | 2.07 ms / 2.2 MB | 1.81 ms / 1.1 MB | 0.88× | 0.50× |
| 1,000 | 96.4 ms / 21.4 MB | 93.6 ms / 7.0 MB | 0.97× | 0.33× |
BenchmarkDotNet 0.15, 3 launches, .NET 10, Apple M1 Pro. Lower is better.
How to read it:
- Past a few dozen objects FxMap is on par with or faster than a single joined
ProjectToand allocates a half to a third of the memory, because it fetches each distinct key once instead of joining every row. - With a handful of objects both take well under a millisecond; the fixed cost of one scoped query per distributed key and level shows up (about 0.1 ms here) and FxMap is slower in relative terms.
- At 1,000 orders the in-memory query itself is most of the time (about 84 ms of the 94 ms), so the gap between the two is small there.
- This is a local, single-process comparison on an in-memory provider. With a real database or transport, the cost of the round trips dominates and FxMap's batching by key is what matters; these numbers say nothing about network latency.
To reproduce:
cd FxMap/test/FxMap.Benchmark
dotnet run -c Release -- --filter '*ProjectionBenchmark*' --launchCount 3
Documentation
Visit fxmapper.net for:
- Getting Started Guide
- Configuration Options
- Expression Language Reference
- Data Provider Setup
- Transport Configuration
Community
- Chat and get help on Discord
- Ask questions and share ideas in GitHub Discussions
- Coming from OfX? Read the migration guide
Contributing
Contributions are welcome! See CONTRIBUTING.md or visit our GitHub repository to:
- Report issues
- Submit pull requests
- Request features
License
This project is licensed under the Apache-2.0 license.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
-
net9.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
NuGet packages (10)
Showing the top 5 NuGet packages that depend on FxMap:
| Package | Downloads |
|---|---|
|
FxMap.EntityFrameworkCore
FxMap extension. Use EntityFramework as Data Querying |
|
|
FxMap.gRPC
FxMap extension. Use gRPC as Data transporting |
|
|
FxMap.Nats
Nats.io extension. Use Nats as Data transporting |
|
|
FxMap.RabbitMq
FxMap.RabbitMq extension. Use RabbitMq as Data transporting |
|
|
FxMap.Azure.ServiceBus
Azure ServiceBus extension. Use Azure ServiceBus as Data transporting |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.1.1 | 32 | 10/6/2026 |
| 4.1.0 | 71 | 10/5/2026 |
| 4.0.0 | 111 | 10/5/2026 |
| 3.0.0 | 201 | 10/2/2026 |
| 2.3.5 | 111 | 10/2/2026 |
| 2.3.4 | 111 | 10/2/2026 |
| 2.3.3 | 122 | 10/1/2026 |
| 2.3.2 | 155 | 10/1/2026 |
| 2.3.1 | 313 | 8/21/2026 |
| 2.3.0 | 311 | 6/16/2026 |
| 2.2.2 | 304 | 6/3/2026 |
| 2.2.1 | 298 | 5/31/2026 |
| 2.2.0 | 662 | 5/26/2026 |
| 2.1.1 | 296 | 5/26/2026 |
| 2.1.0 | 434 | 5/7/2026 |
| 2.0.1 | 279 | 4/5/2026 |
| 2.0.0 | 250 | 4/5/2026 |
| 1.0.3 | 270 | 3/15/2026 |
| 1.0.2 | 250 | 3/7/2026 |
| 1.0.1 | 270 | 3/6/2026 |