33

I instantiated a context and want to write a simple query:

var result = db.Set.Where(x => x.Id == num).Select(whatever);

and I can't get rid of the red squiggly under Where complaining about an ambiguous invocation between System.Collections.Generic.IEnumerable and System.Linq.IQueryable. System.Linq is specifically referenced, and System.Collections.Generic is not referenced anywhere in the project. How can I tell the code that I want to use System.Linq.IQueryable?

Lauren Rutledge
  • 1,195
  • 5
  • 18
  • 27
pthalacker
  • 2,056
  • 3
  • 20
  • 37

5 Answers5

42

This problem is normally caused by a failure in type inference from in the expression provided to the Where statement. As was mentioned in the comments above it is 100% caused by the assignment operator in the lambda returning an int instead of a bool.

To be clear - where you have

var result = db.Set.Where(x => x.Id = num).Select(whatever);

You should have

var result = db.Set.Where(x => x.Id == num).Select(whatever);

Another good (and more common) example of this is something like this

public class Elem 
{
    public bool IsSomething {get;set;}                    
    public bool? IsSomethingElse {get;set;}
}

Then if you do the following query, which looks very reasonable at fist glance, it will fail to compile with the rather puzzling error of "abiguous invocation"

IQueryable<Elem> queryable = GetQueryable();
var result = queryable.Where(e => e.IsSomething && e.IsSomethingElse).ToList();

If you weren't writing this statement inside a lambda then you would get a more meaningful error of

"Cannot apply operator '&&' to operands of type 'System.Nullable<bool>' and 'bool'"

Which would immediately tell you that you are failing to return a boolean.

Arne Evertsson
  • 19,693
  • 20
  • 69
  • 84
Rhys Bevilaqua
  • 2,102
  • 17
  • 20
2

The problem that many people will have is because IQueryable inherits from IEnumerable, and they both have their own implementation of the various LINQ statements.

Rhys's answer covers another situation than this. If you implement what I say below, and still receive the error, then you are probably running into his situation.

This answer shows the differences between IEnumerable and IQueryable. This article explains what .AsQueryable() is good for.

In the case of this particular question, .AsQueryable() is not the right way to do this because the purpose is primarily for conversion of IEnumerables into pseudo-queryables. The proper way to do this is to be explicit to the compiler what your object is.

IQueryable<whateverSet> dbSet = db.Set;
var result = dbSet.Where(x => x.Id == num).Select(whatever);

This is telling the compiler what dbSet is explicitly rather than trying to execute a cast statement as in the case of .AsQueryable().

The addition of var in C# 3.0 was fantastic for people coming from loosely typed languages like PHP, however it fools folks into thinking that the compiler will always be able to just "figure it out". There are plenty of times this isn't the case, and casting is NOT the solution.

Jim Yarbro
  • 2,063
  • 15
  • 21
  • 1
    Once again people keep missing his error. notice that he has a single `=` in his comparison!!! He is returning an `int` to the expression and not a `boolean`. You on the other had have fixed his error and put `==` in. – Rhys Bevilaqua Apr 09 '15 at 01:57
  • Your answer is one of two situations I've found that could cause the same squiggly, and the people who find this thread in the future might not see which problem it is. Given that the OP selected his own answer using AsQueryable(), that tells me he merely had a typo in his example code above, and the == is merely a red herring, not the cause of his issue. That doesn't mean your answer is wrong for other people's situations. – Jim Yarbro Apr 10 '15 at 07:50
  • @JimYarbro his answer is specifically the cause of the problem the OP's question is mentioning. If the OP typo'd their question then they need to fix it, or accept the answer that actually answers the question as it's written. – Nick Coad Jun 29 '16 at 01:10
1

Got it. People don't seem to like this answer, but it solved the problem I described in the question.

db.Set.AsQueryable().Where(...
pthalacker
  • 2,056
  • 3
  • 20
  • 37
  • _What_ is db.Set? I don't understand how you can't work with generics. It really doesn't look healthy. – Gert Arnold Nov 10 '13 at 18:59
  • 2
    This solution does not make a functional change to the code, the implementation of AsQueryable tests if the source is already a queryable - and if it is it casts it to IQueryable and returns it. – Rhys Bevilaqua Jan 14 '15 at 02:11
  • 2
    It may not change the code, but it clears up the ambiguity which was the cause of my problem. – pthalacker Jan 21 '15 at 01:31
  • @pthalacker i don't think it did, I'm betting you made a different change that cleared up the ambiguity. What my previous comment said is that to the compiler the two statements are not just equivalent they are the **same**. – Rhys Bevilaqua Feb 03 '15 at 01:10
  • It makes no sense to leave this question here. It doesn't help anyone. – pthalacker Feb 20 '15 at 23:59
  • 2
    Despite the down votes, this answer solved my red squiggly problem. – Zarepheth Mar 04 '15 at 17:03
  • 1
    This should not be the accepted answer. The problem is the use of the assignment operator '=' in the where expression instead of the equality operator '=='. This is correctly answered by Rhys Bevilaqua below for those who arrive here in future. – Nick Coad Jun 29 '16 at 01:06
1

I had this problem - In my case the model was in a separate project from the calling code. The calling code did not have a reference to EF. Adding reference to EF in calling project fixed it for me.

Simon H
  • 508
  • 1
  • 5
  • 18
0

In my particular case I was getting the same error but the cause was not having a reference to System.Linq. Adding the reference fixed the error in this particular case.

firebird
  • 21
  • 2