Create a Tuple in a Linq Select

C#Entity FrameworkLinqTuples

C# Problem Overview


I'm working with C# and .NET Framework 4.5.1 retrieving data from a SQL Server database with Entity Framework 6.1.3.

I have this:

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

And when I run it, I get this message:

> Only parameterless constructors and initializers are supported in LINQ > to Entities.

I don't know how I have to create the Tuple because all the examples that I have found are mostly like this one.

I have tried this:

codes = codesRepo.SearchFor(predicate)
      .Select(c => Tuple.Create(c.Id, c.Flag))
      .ToList();

And get this error:

> LINQ to Entities does not recognize the method > 'System.Tuple`2[System.String,System.Byte] > Create[String,Byte](System.String, Byte)' method, and this method > cannot be translated into a store expression.

Where is the problem?

C# Solutions


Solution 1 - C#

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 - C#

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 - C#

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 - C#

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 - C#

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

Solution 6 - C#

Just my two cents: this has caught me out a few times with the type names:

A few noddy examples:

    private Tuple<string, byte> v1()
    {
        return new Tuple<string, byte>("", 1);
    }

    private (string, int) v2()
    {
        return ("", 1);
    }

    private (string Id, byte Flag) v3()
    {
        return ("", 1);
    }

Regards.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVansFannelView Question on Stackoverflow
Solution 1 - C#Ivan StoevView Answer on Stackoverflow
Solution 2 - C#Rafael MerlinView Answer on Stackoverflow
Solution 3 - C#DhuntView Answer on Stackoverflow
Solution 4 - C#octaviocclView Answer on Stackoverflow
Solution 5 - C#MohammadSooriView Answer on Stackoverflow
Solution 6 - C#IbrarMumtazView Answer on Stackoverflow