Create a Tuple in a Linq Select

Solution 1:

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

Solution 2:

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

Solution 3:

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

Solution 4:

In linq to entities you can project onto an anonymous type or onto a DTO.To avoid that issue you can use AsEnumerable extension method:

codes = codesRepo.SearchFor(predicate).AsEnumerable().
      .Select(c => new Tuple<string, byte>(c.Id, c.Flag))
      .ToList();

This method lets you work with Linq to Object instead Linq to Entities, so after call it,you can project the result of your query in whatever you need.The advantage of using AsEnumerable instead ToList is that AsEnumerable does not execute the query, it preserves deferred execution. It's good idea always filter your data first before call one of these methods.

Solution 5:

Use this method to do this and use the async.

var codes = await codesRepo.SearchFor(predicate)
                    .Select(s => new
                    {
                        Id = s.Id,
                        Flag = s.Flag
                    }).FirstOrDefaultAsync();

                var return_Value = new Tuple<string, byte>(codes.Id, codes.Flag);