Create a Tuple in a Linq Select
While the answer by octavioccl works, it's better to first project the query result into anonymous type, and then switch to enumerable and convert it to tuple. This way your query will retrieve from the data base only the fields needed.
codes = codesRepo.SearchFor(predicate)
.Select(c => new { c.Id, c.Flag })
.AsEnumerable()
.Select(c => new Tuple<string, byte>(c.Id, c.Flag))
.ToList();
Note: The above rule applies to EF6. EF Core naturally supports tuples (in projection or as join/group keys) via tuple constructor, e.g. the original query simply works
codes = codesRepo.SearchFor(predicate)
.Select(c => new Tuple<string, byte>(c.Id, c.Flag))
.ToList();
but not the Tuple.Create
method (EF Core 2.x).
Try this:
codes = codesRepo.SearchFor(predicate)
.Select(c => Tuple.Create(c.Id, c.Flag))
.ToList();
Been informed this isn't accepting in LINQ to entities.
Another option would be to pull the result into memory before selecting. If you are going to do this I would recommend doing all of the filtering before the .AsEnumerable() as it means you are only pulling back results that you want as opposed to pulling back the whole table and then filtering.
codes = codesRepo.SearchFor(predicate).AsEnumerable()
.Select(c => Tuple.Create(c.Id, c.Flag))
.ToList();
as well Tuple.Create(c.Id, c.Flag) could be changed to new Tuple(c.Id, c.Flag) if you want to make the code a bit more explicit in the tuples types
Just an updated answer for C# 7, now you can use a simpler syntax to create ValueTuples.
codes = codesRepo.SearchFor(predicate)
.Select(c => new { c.Id, c.Flag })
.AsEnumerable()
.Select(c => (c.Id, c.Flag))
.ToList();
You can even name the properties of the tuple now:
codes = codesRepo.SearchFor(predicate)
.Select(c => new { c.Id, c.Flag }) // anonymous type
.AsEnumerable()
.Select(c => (Id: c.Id, Flag: c.Flag)) // ValueTuple
.ToList();
So instead of using it as Item1 or Item2 you can access it as Id or Flag.
More docs on choosing-between-anonymous-and-tuple