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?
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).