I'm trying to pull back a list of Order records where each one carries a nested Customer object. I'm using Dapper's Query<Order, Customer, Order> overload, but no matter what I do, the Customer properties stay null after materialization.
Here's the mapper I've been using:
// Mapper attempt
private Order MapOrder(Order order, Customer customer)
{
order.Customer = customer; // Never sticks
return order;
}
I've double-checked the splitOn column against my SELECT list and it lines up. The query itself returns rows fine in SSMS. Is there a registration step I'm missing, or does the overload signature need to change? I'd appreciate any patterns that keep the parent populated without bloating the result set.
Dapper multi-mapping works by dividing each result row into column segments. It uses the
splitOnvalue to decide where one mapped object ends and the next begins. If that boundary doesn’t match your SELECT column order, the objects can be built from the wrong columns—or a mapped object can come back null.For a parent and child, put the parent columns first, followed by the child columns, and make the child’s key the split point:
Here,
splitOn: "Id"marks the secondIdcolumn—the start of the child segment. The firstIdbelongs to the parent. This relies on the explicit column order; usingSELECT *can make the boundary ambiguous, especially when both tables have anIdcolumn.Also check that the generic types are in the same order as the column segments:
Parent, Childfor the query above. With aLEFT JOIN, a missing child may legitimately map to null, but the parent should still be present. If the parent itself is null, inspect the returned row and confirm its first parent column (usually the key) is non-null and that the query actually returns a row.