← Back

Anonymous Types in EF Core

2026-01-12 16:49 · 👁 31954

#c##ef core

🔍 Anonymous Types in EF Core — the secret weapon for clean, fast queries

If you’re still doing Select(entity => entity) and then mapping everything in memory… you’re probably over-fetching.

Anonymous types let you shape the result inside SQL, bringing back only what you need — with zero extra DTO classes.


✅ 1) Project only what you need (faster + less memory)

var users = await db.Users
    .Where(u => u.IsActive)
    .Select(u => new
    {
        u.Id,
        u.Name,
        u.Email
    })
    .ToListAsync();
-- Generated query execution expression:

SELECT u.Id, u.Name, u.Email
FROM Users AS u
WHERE u.IsActive
ORDER BY u.Id ASC

This becomes a SQL query selecting only those columns.


✅ 2) Anonymous type as a “mini view model” for screens

var grid = await db.Orders
    .Where(o => o.Status == OrderStatus.Open)
    .Select(o => new
    {
        o.Id,
        Customer = o.Customer.Name,
        o.Total,
        o.CreatedAt
    })
    .OrderByDescending(x => x.CreatedAt)
    .ToListAsync();
-- Generated query execution expression:

SELECT o.Id, c.Name AS Customer, o.Total, o.CreatedAt
FROM Orders AS o
INNER JOIN Customers AS c ON o.CustomerId == c.Id
WHERE o.Status == 'Open'
ORDER BY o.CreatedAt DESC

✅ 3) Grouping with a composite key (anonymous type = key)

var summary = await db.Sales
    .GroupBy(s => new { s.StoreId, s.ProductId })
    .Select(g => new
    {
        g.Key.StoreId,
        g.Key.ProductId,
        Qty = g.Sum(x => x.Quantity),
        Revenue = g.Sum(x => x.Quantity * x.UnitPrice)
    })
    .ToListAsync();
-- Generated query execution expression:

SELECT s.StoreId, s.ProductId, SUM(s.Quantity) AS Qty, SUM(s.Quantity * s.UnitPrice) AS Revenue
FROM Sales AS s
GROUP BY s.StoreId, s.ProductId
ORDER BY s.StoreId ASC, s.ProductId ASC

Anonymous types shine here because they implement value-based equality automatically.


✅ 4) Join without pain (especially when you need multiple fields)

var data = await db.Users
    .Join(db.Subscriptions,
        u => u.Id,
        s => s.UserId,
        (u, s) => new
        {
            u.Name,
            s.Plan,
            s.ExpiresAt
        })
    .ToListAsync();
-- Generated query execution expression:

SELECT u.Name, s.Plan, s.ExpiresAt
FROM Users AS u
INNER JOIN Subscriptions AS s ON u.Id == s.UserId
ORDER BY s.ExpiresAt ASC

⚠️ Gotchas (things that bite)

  • Don’t return anonymous types from public methods (they’re internal to the method scope).
  • Avoid non-translatable expressions inside projections (EF can only translate certain .NET operations to SQL).
  • If you need reuse, promote the shape to a DTO/record — but start with anonymous types for speed.

Rule of thumb

✅ Anonymous types = perfect for queries + shaping data
✅ DTOs/records = best for boundaries (APIs, services, shared contracts)

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please reload the page.