Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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)'
like image 227
Elisabeth Avatar asked Sep 22 '15 09:09

Elisabeth


3 Answers

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

like image 69
Panagiotis Kanavos Avatar answered Sep 24 '22 04:09

Panagiotis Kanavos


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();
like image 28
codekaizen Avatar answered Sep 22 '22 04:09

codekaizen


In Linq you need to use the static method of equals. Do this instead and it will work:

where l.ApplicationName.Equals(applicationName, StringComparison.InvariantCultureIgnoreCase)
like image 37
Nacho Avatar answered Sep 21 '22 04:09

Nacho