Search code examples
c#entity-framework-core.net-7.0ef-core-7.0

Project EF Core 7 result to named tuple


I'm using EF Core 7. I want to perform server evaluation and project to a named tuple.

I tried:

var products = await _context.Products.Select(x => (x.Id, x.Name)).ToListAsync();

Which gives:

An expression tree may not contain a tuple literal.

I could do this with a regular tuple (Tuple.Create()) or an anonymous object (new {}), but I'd like to use a named tuple, if possible.

Can this be done somehow?


Solution

  • No, currently it is not possible because it is not possible to use value tuples literals in the expression trees. You can monitor following issues/discussions at the github:

    If you really-really want to use value tuples the only way is to map to them after the materialization of the query, but I would argue that it is rather pointless in most cases. Something like the following:

    var products = _context.Products
       .Select(x => new {x.Id, x.Name})
       .AsEnumerable()
       .Select(ac => (ac.Id, ac.Name))
       .ToList();
    

    Though there is a trick with method indirection which can be used:

    class SomeClass // local functions can't be used
    {
        public static (int Id, int Name) CreateNamedValueTuple(int t1, int t2) => (t1, t2);
    }
    
    var products = await _context.Products
        .Select(x => SomeClass.CreateNamedValueTuple(x.Id, x.Name))
        .ToListAsync();
    

    Though personally I would just used a C# 9 record feature which allows easy type creation (or C# 10 record struct).