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?
The Tuple<T> class was introduced in . NET Framework 4.0. A tuple is a data structure that contains a sequence of elements of different data types.
LINQ Select operator is used to return an IEnumerable collection of items, including the data performed on the transformation of the method. By using Select Operator, we can shape the data as per our needs. In it, we can use two syntax types; let's see each method working flow.
By default, LINQ queries return a list of objects as an anonymous type. You can also specify that a query return a list of a specific type by using the Select clause.
Let's start off by acknowledging that using the LINQ operators (such as Select and Where ) does typically result in very slighly slower code than if you wrote a for or foreach loop to do the same thing. This is acknowledged in the Microsoft documentation: LINQ syntax is typically less efficient than a foreach loop.
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).
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With