Incorrect number of arguments supplied for call to method 'Boolean Equals

14,219

Solution 1

This is a runtime error because you are likely running against a Linq query provider, which takes an expression the C# compiler created from your C# code and executes it at runtime. The provider likely can't translate this overload of Equals.

Try changing your Linq query to be:

(from l in context.Languages
join t in context.Translations on l.ISO639_ISO3166 equals t.ISO639_ISO3166).AsEnumerable()
.Where(l => string.Equals(l.ApplicationName, applicationName, StringComparison.InvariantCultureIgnoreCase))
.Select(new Translation
              {
                  Key = t.Key,
                  Text = t.Text
              }).ToListAsync();

Solution 2

First of all, SQL string comparisons are case-insensitive, or rather, the most common collations are case-insensitive.

You shouldn't need to use String.Equals at all. Try executing your query without the String.Equals call.

If, for some reason, the query fails to return results, there may be a problem with the arguments or the data. You should try to execute the equivalent SQL statement directly and check whether there are any matching results.

String case would be an issue only if the underlying column's collation was modified to a string-sensitive one. This would be very unusual. In fact, the difficult part is getting LINQ to EF to do a case-sensitive query.

As for the error itself, it's caused because String.Equals can't be translated to SQL. LINQ by itself doesn't execute queries, it's just a language. LINQ providers are responsible for translating queries to the underlying language and executing them.

Some providers, like LINQ to SQL, will parse whatever they can, load the result in memory and pass it to LINQ to Object for the unsupported operations. This typically results in very bad performance. In your case, your query would load all translations in memory and then try to filter them.

LINQ to EF on the other hand doesn't allow this to prevent performance problems. Queries that can't be translated, aren't executed. String.Equals in particular can't be translated to SQL as string comparisons are controlled by culture-specific collations. There is no equivalent to the Invariant Culture.

If your table is case-sensitive, you'll have to change the collation used for comparisons, eg to Latin1_CI_AS. This SO question describes various ways to do that

Share:
14,219

Related videos on Youtube

Elisabeth
Author by

Elisabeth

I am a develoBee summ summ :P

Updated on September 15, 2022

Comments

  • Elisabeth
    Elisabeth over 1 year

    Why do I get an argument exception saying I pass the wrong number of arguments to string.equals method?

    I pass THREE arguments and that should be correct. Actually it should throw a compile time error not runtime...

    Do you see the error?

    var translations = await (from l in context.Languages
                      join t in context.Translations on l.ISO639_ISO3166 equals t.ISO639_ISO3166
                      where string.Equals(l.ApplicationName, applicationName, StringComparison.InvariantCultureIgnoreCase)
                      select new Translation
                      {
                          Key = t.Key,
                          Text = t.Text
                      }).ToListAsync();
    

    UPDATE

    Test Name:  GetTranslations
    Test FullName:  TaaS.IntegrationTests.Tests.TranslationRepositoryTests.GetTranslations
    Test Source:    C:\test\TaaS-WebApplication\TaaS.IntegrationTests\Tests\TranslationRepositoryTests.cs : line 17
    Test Outcome:   Failed
    Test Duration:  0:00:00,0473367
    
    Result StackTrace:  
    at System.Linq.Expressions.Expression.GetMethodBasedBinaryOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, Boolean liftToNull)
       at System.Linq.Expressions.Expression.Equal(Expression left, Expression right, Boolean liftToNull, MethodInfo method)
       at System.Data.Entity.Core.Objects.ELinq.LinqExpressionNormalizer.VisitMethodCall(MethodCallExpression m)
       at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp)
       at System.Linq.Expressions.EntityExpressionVisitor.VisitLambda(LambdaExpression lambda)
       at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp)
       at System.Linq.Expressions.EntityExpressionVisitor.VisitUnary(UnaryExpression u)
       at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp)
       at System.Linq.Expressions.EntityExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original)
       at System.Linq.Expressions.EntityExpressionVisitor.VisitMethodCall(MethodCallExpression m)
       at System.Data.Entity.Core.Objects.ELinq.LinqExpressionNormalizer.VisitMethodCall(MethodCallExpression m)
       at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp)
       at System.Linq.Expressions.EntityExpressionVisitor.VisitExpressionList(ReadOnlyCollection`1 original)
       at System.Linq.Expressions.EntityExpressionVisitor.VisitMethodCall(MethodCallExpression m)
       at System.Data.Entity.Core.Objects.ELinq.LinqExpressionNormalizer.VisitMethodCall(MethodCallExpression m)
       at System.Linq.Expressions.EntityExpressionVisitor.Visit(Expression exp)
       at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter..ctor(Funcletizer funcletizer, Expression expression)
       at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.CreateExpressionConverter()
       at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
       at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClassc.<GetResultsAsync>b__a()
       at System.Data.Entity.Core.Objects.ObjectContext.<ExecuteInTransactionAsync>d__3d`1.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<ExecuteAsyncImplementation>d__9`1.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Data.Entity.Utilities.TaskExtensions.CultureAwaiter`1.GetResult()
       at System.Data.Entity.Core.Objects.ObjectQuery`1.<GetResultsAsync>d__e.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Data.Entity.Utilities.TaskExtensions.CultureAwaiter`1.GetResult()
       at System.Data.Entity.Internal.LazyAsyncEnumerator`1.<FirstMoveNextAsync>d__0.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Data.Entity.Infrastructure.IDbAsyncEnumerableExtensions.<ForEachAsync>d__5`1.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       at TaaS.Repository.TranslationRepository.<GetTranslationsAsync>d__2.MoveNext() in C:\_REPOSITORIES\taas-application\TaaS-WebApplication\TaaS.Repository\TranslationRepository.cs:line 20
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       at TaaS.IntegrationTests.Tests.TranslationRepositoryTests.GetTranslations() in C:\_REPOSITORIES\taas-application\TaaS-WebApplication\TaaS.IntegrationTests\Tests\TranslationRepositoryTests.cs:line 45
    Result Message: 
    Test method TaaS.IntegrationTests.Tests.TranslationRepositoryTests.GetTranslations threw exception: 
    System.ArgumentException: Incorrect number of arguments supplied for call to method 'Boolean Equals(System.String, System.String, System.StringComparison)'
    
    • JBond
      JBond over 8 years
      If they weren't strings. They would both be compile time errors. Elisabeth is seeing a runtime error.
    • usr
      usr over 8 years
      Provide the full error.
    • TheLethalCoder
      TheLethalCoder over 8 years
      Is the error for Boolean equals like the title says or string.equals as the question says?
  • Ivan Stoev
    Ivan Stoev over 8 years
    While this is the correct answer, is there any list of a functions that are required to be supported by any Linq query provider? I know about Canonical Functions, but AFAIK they are EF specific. Many people get confused when switching from IEnumerabe<T> to IQueryable<T> - everything happily compiles and then they start getting those runtime errors.
  • codekaizen
    codekaizen over 8 years
    It depends on the provider.
  • Ivan Stoev
    Ivan Stoev over 8 years
    I see. So nothing similar to ANSI SQL like ECMA LINQL :-) Thanks.
  • Elisabeth
    Elisabeth over 8 years
    @codekaizen copy/paste your code I can not make it compile.
  • Elisabeth
    Elisabeth over 8 years
    I changed the comparison to "==" because that is what I wanted remembering again that the sql comparison is case insensitive thanks to @Panagiotis Kanavos.
  • Elisabeth
    Elisabeth over 8 years
    Thanks for the case-insensitive comment. That really helped!
  • Stephen Holt
    Stephen Holt over 7 years
    This answer doesn't work. The string.Equals mentioned is still the version that is not supported by Entity Framework.
  • Stephen Holt
    Stephen Holt over 7 years
    Yes, I think this is correct. However, I find it slightly annoying. Code First should not be making so many assumptions about the database that you can put .Where(a == b) as a C# condition and expect it to match where a and b aren't the same case. C# rules should apply regardless.
  • Panagiotis Kanavos
    Panagiotis Kanavos over 7 years
    @StephenHolt it's LINQ to EF, not Code First. Furthermore, it's making fewer assumptions precisely to avoid generating unexpectedly bad queries, like LINQ to SQL did. Finally, trying to apply C# rules to a completely different language is a recipe for performance bugs. LINQ isn't C# specific to begin with.
  • Panagiotis Kanavos
    Panagiotis Kanavos over 7 years
    @StephenHolt In SQL's case, it would be a disaster because collation is column specific. It affects indexing. Trying to use a different collation invalidates indexes and results in full table scans
  • Panagiotis Kanavos
    Panagiotis Kanavos over 7 years
    This is not a good answer because AsEnumerable() loads all rows in memory, then tries to apply the WHERE condition without any benefit of indexing. Instead of loading eg 10 rows from a 100K table, it will load all 100K rows
  • Panagiotis Kanavos
    Panagiotis Kanavos over 7 years
    @IvanStoev this is not the correct answer, actually it's a common bug - switching to Enumerable executes the query and loads everything in memory.
  • Panagiotis Kanavos
    Panagiotis Kanavos over 7 years
    @StephenHolt, since we are talking about translations, different languages have very different matching rules between upper and lower case. The Turkish I is the perfect example - there are dotted and dotless variants
  • Ivan Stoev
    Ivan Stoev over 7 years
    @PanagiotisKanavos While you are right in general, looks like EF Core consider loading whole tables in memory not a bug, but feature - it does that by default for any expression it cannot translate to SQL :)
  • Panagiotis Kanavos
    Panagiotis Kanavos over 7 years
    @IvanStoev source? Because it does no such thing. You can't load data from a database without SQL - SQL Server doesn't listen to anything except SQL. You can easily verify this by using SQL Server Profiler. Perhaps you confuse EF Core with the planned (but not released) NoSQL support?
  • Ivan Stoev
    Ivan Stoev over 7 years
    @PanagiotisKanavos Sure, I meant the LINQ query not fully translated to SQL like in EF6. But something like the above, only made automatically for you :) See, I'm kidding, but it's really a big problem, and MS team made it a default feature. They call it mixed query execution or something like that.
  • Sergey
    Sergey over 4 years
    While this may work, this is the wrong solution. Since SQL string comparisons are already case insensitive, simply doing a l.ApplicationName == applicationName comparison will do a case insensitive compare, because the LINQ expression will just be translated into a SQL statement. The error is happening by DESIGN, don't try to "make it work".
  • OutstandingBill
    OutstandingBill over 4 years
    @StephenHolt - I wonder if, to achieve what you'd like to see, you could do .ToList().Where(a == b)? Haven't tried it, just suggesting. I'd imagine that brings evaluation of Where into LINQ to Object.
  • codekaizen
    codekaizen over 4 years
    @Sergey SQL string comparison is not always case insensitive. The database collation determines this.
  • Sergey
    Sergey over 4 years
    Yep, good point @codekaizen. Maybe the answer can be updated to mention that.
  • Stephen Holt
    Stephen Holt over 4 years
    @OutstandingBill yes, I imagine that would work. By calling ToList() you're bringing the processing of the conditional in-house, and it will be processed using C# rules. It's not necessarily a good thing to do, though, because it will cause the whole set to be loaded from DB into memory before applying the conditional.