147

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?

2
  • Looks like you'll need to create a strongly typed object. But yes, good question; upvoted. Commented Nov 5, 2015 at 13:05
  • .Select(_ => new ValueTuple<string, byte>((c.Id, c.Flag)) Commented Feb 28, 2023 at 14:08

7 Answers 7

190

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

Sign up to request clarification or add additional context in comments.

5 Comments

Very good solution - Thanks! ... What about if I'd had to extend this solution by another nullable value? .Select(c => new { c.Id, c.Flag, c.Foo?.Code }) does not work.
@skyfrog The operator ?. is not supported in expression trees. But other than that, you can extend the anonymous type with as many values you want - just don;t forget to name them when needed :) e.g. c => new { c.Id, c.Flag, Code = (int?)c.Foo.Code }
Great! Many thanks @Ivan for your reply. I was so close! ... but it is always easy to say while looking back ;-)
Great answer, can be used with EF-Entities.. e.g. dbCtx.MyEntity.Where().Select( .. to anon object...).etc...
Just a note, Linq does not accept named Tuple in my case, but I can live with that. This approach works sufficiently in my case.
107

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

Comments

17

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

1 Comment

Sorry, it doesn't work. I have updated my question with more details.
12

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.

1 Comment

-1 This does not do the same thing as was asked by the OP. Sometimes, being able to create Tuples in a query, for Joining purposes is important.
1

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

Comments

0

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.

3 Comments

The syntax you posted does not work. What you probably meant to write is public (string Id, byte Flag) SearchFor(Expression predicate), but this is beside the point. Two cents shouldn't be an answer, but a comment.
I updated my answer - i should have checked it before posting. I disagree; all info is useful to all visitors who land on this page regardless how it is posited. Comments do not convey intent as well as answer thanks to answers.
I do agree that added content is good and comments don't cater well to code examples. Thanks for editing, now it is clear that this is not an answer to the OP's question (but may help with tuple related problems).
-1

You also can use record.

https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/records

private record Code(string Id, byte Flag);

then use it like

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

later you can use a named property instead of a .Item1, .Item2

var code = codes.First();
...code.Id; 
...code.Flag;

3 Comments

That defeats the purpose of creating a Tuple: not having to define a named structure. Also, tuples do have named members since a couple of years.
@gert-arnold-is-on-strike Named tuples is not supported on linq-sql. so you have to do a select with anonymous to read, materialize (asEnumerable, toList, etc), and then another select for named tuples... which it is cumbersome. In Linq-SQL, I tends to use a lot of anonymous type, or some classes or records, but I try to avoid tuples for the reason above.
Sure, it's awkward, but it's a way to return fixed-format typed data from a method w/o having to define a class/struct etc. I think that's OP's purpose.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.