Interview question
Implement an atomic bulk status update
Validates a bounded command set completely before applying all updates in one SaveChanges transaction.
TL;DR
Validates a bounded command set completely before applying all updates in one SaveChanges transaction.
Bulk input bounds, duplicate detection, preflight validation, atomic persistence, missing rows, and conflicts.
Practice the problem like a real interview: restate, reason, implement, and test.
Accept order ids and target statuses. Reject duplicate ids, unsupported transitions, or missing rows before modifying anything. Commit all valid updates together.
Next in API Implementation Labs: Capability Policy
If one of 20 ids is missing, the response identifies it and none of the other 19 orders change.
I validate command shape first, load every target in one query, compare requested and loaded ids, then validate domain transitions. Only after the whole batch passes do I mutate tracked entities and save once.
app.MapPost("/orders/bulk-status", async Task<IResult> (
BulkStatusRequest request, AppDbContext db, CancellationToken ct) =>
{
if (request.Items is not { Count: > 0 and <= 100 })
return Results.ValidationProblem(new() {
["items"] = ["Provide between 1 and 100 updates."]
});
var ids = request.Items.Select(x => x.Id).ToArray();
if (ids.Distinct().Count() != ids.Length)
return Results.ValidationProblem(new() {
["items"] = ["Each order id may appear only once."]
});
var orders = await db.Orders.Where(x => ids.Contains(x.Id)).ToListAsync(ct);
var missing = ids.Except(orders.Select(x => x.Id)).ToArray();
if (missing.Length > 0)
return Results.NotFound(new ProblemDetails {
Title = "Some orders were not found",
Extensions = { ["missingIds"] = missing }
});
var byId = orders.ToDictionary(x => x.Id);
var errors = new Dictionary<string, string[]>();
foreach (var item in request.Items) {
if (!byId[item.Id].CanMoveTo(item.Status))
errors[$"items[{Array.IndexOf(ids, item.Id)}].status"] =
[$"Cannot move from {byId[item.Id].Status} to {item.Status}."];
}
if (errors.Count > 0) return Results.ValidationProblem(errors);
foreach (var item in request.Items) byId[item.Id].MoveTo(item.Status);
try {
await db.SaveChangesAsync(ct); // One SaveChanges is transactional.
} catch (DbUpdateConcurrencyException) {
return Results.Conflict(new ProblemDetails {
Title = "One or more orders changed during the update",
Status = StatusCodes.Status409Conflict
});
}
return Results.NoContent();
}).RequireAuthorization("orders.manage");
The all-or-nothing contract is easier to retry and reason about than an undocumented mix of successes and failures. For intentionally partial workflows, return an explicit per-item result model instead.
Share the question with a concise Core-answer excerpt and invite other developers to add their perspective.
Help improve the interview library.
Say thanks with a standalone, one-time $5 contribution. No account required.
Aporeon is shaped by Aleksandar Tomovski, a software developer with experience on both sides of technical interviews. Content is reviewed for accuracy, natural spoken delivery, useful depth, and honest trade-offs.