[CSHARP-423] .Where(item=>stringProperty.ToLower() == lowerCaseCheckValue) throws "Unsupported where clause:" exception Created: 30/Mar/12  Updated: 02/Apr/15  Resolved: 11/Apr/12

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: 1.4
Fix Version/s: 1.4.1

Type: Bug Priority: Major - P3
Reporter: Mennan Kara Assignee: Robert Stam
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Same exception gets thrown with .ToLowerInvariant(), ToUpper(), ToUpperInvariant(), Trim(), SubString(s,l). I'm guessing that the list goes on like this.



 Comments   
Comment by Robert Stam [ 11/Apr/12 ]

The following:

ToLower
ToUpper
Trim
TrimEnd
TrimStart

can be combined with:

Contains
EndsWith
StartsWith

The following can be used stand alone:

Equals (static and instance method)
IndexOf(c) == i
IndexOf(s) == i
IndexOf(c, j) == i
IndexOf(s, j) == i
IndexOf(c, j, k) == i
IndexOf(s, j, k) == i
IndexOfAny(carray) == i
IndexOfAny(carray, j) == i
IndexOfAny(carray, j, k) == i
IsNullOrEmpty
Length == n

The following are not supported (but might be in the future):

IsNullOrWhiteSpace (introduced in .NET Framework 4)
LastIndexOf
LastIndexOfAny
PadLeft
PadRight
Remove
Substring
ToLowerInvariant (use ToLower instead, and server always uses ordinal comparisons)
ToUpperInvariant (use ToUpper instead, and server always uses ordinal comparisons)

Comment by Mennan Kara [ 31/Mar/12 ]

Very nice thinking about regular expressions. Thanks.

Comment by Robert Stam [ 30/Mar/12 ]

Looks like lots of string methods could be supported in LINQ queries by translating the expressions to MongoDB queries using regular expressions. Here's a list of possible translations:

d is the document
p is a property of type string

d.p.Contains("abc") => { p : /abc/ }
d.p.EndsWith("abc") => { p : /abc$/ }
d.p.Equals("abc") => { p : "abc" }
string.Equals(d.p, "abc") => { p : "abc" }
string.IsNullOrEmpty(d.p) => { $or : [{ p : { $exists : true, $type : 10 } }, { p : "" }] }
string.IsNullOrWhitespace(d.p) => { $or : [{ p : { $exists : true, $type : 10 } }, { p : /^[ \t]*$/ }] }
d.p.StartsWith("abc") => { p : /^abc/ }
d.p.Substring(1) == "bc" => { p : /^.{1}bc$/s }
d.p.Substring(1, 2) == "bc" => { p : /^.{1}bc/s }
d.p.ToLower() == "abc" => { p : /^abc$/i }
d.p.ToUpper() == "ABC" => { p : /^ABC$/i }
d.p.Trim() == "abc" => { p : /^[ \t]*abc[ \t]*$/ }
d.p.TrimEnd() == "abc" => { p : /^abc[ \t]*$/ }
d.p.TrimStart() == "abc" => { p : /^p[ \t]*abc$/ }
d.p[1] == 'b' => { p : /^.{1}b/s }
d.p.Length == 3 => { p : /^.{3}$/s }

Combining multiple methods would be tricker. An example would be:

d.p.Substring(1, 2).ToLower() == "bc" => { p : /^.{1}bc/is }

Comment by Robert Stam [ 30/Mar/12 ]

Not all LINQ queries can be turned into equivalent MongoDB queries, because C# allows you to write expressions that don't have any equivalent in the MongoDB query language.

Unless I am missing something, none of the expressions you listed have an equivalent in the MongoDB query language.

Some of them might be expressible using regular expressions though. I'll investigate that.

Comment by Mennan Kara [ 30/Mar/12 ]

Also doesn't support string.Length

            var problem = collection.AsQueryable<OperationLog>().Where(a => a.Area.Length == 5).ToList();

System.NotSupportedException was unhandled
  HResult=-2146233067
  Message=LINQ queries on fields or properties of class String are not supported because the serializer for String does not implement the GetMemberSerializationInfo method.
  Source=MongoDB.Driver
  StackTrace:
       at MongoDB.Driver.Linq.SelectQuery.GetSerializationInfoMember(IBsonSerializer serializer, MemberExpression memberExpression) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 985
       at MongoDB.Driver.Linq.SelectQuery.GetSerializationInfo(IBsonSerializer serializer, Expression expression) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 888
       at MongoDB.Driver.Linq.SelectQuery.GetSerializationInfo(Expression expression) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 880
       at MongoDB.Driver.Linq.SelectQuery.BuildComparisonQuery(BinaryExpression binaryExpression) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 433
       at MongoDB.Driver.Linq.SelectQuery.BuildQuery(Expression expression) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 768
       at MongoDB.Driver.Linq.SelectQuery.BuildQuery() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 113
       at MongoDB.Driver.Linq.SelectQuery.Execute() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 122
       at MongoDB.Driver.Linq.MongoQueryProvider.Execute(Expression expression) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\MongoQueryProvider.cs:line 147
       at MongoDB.Driver.Linq.MongoQueryable`1.GetEnumerator() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\MongoQueryable.cs:line 81
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
       at JetArena.ConsoleApp.Program.Main(String[] args) in D:\JetArena\JetArena.ConsoleApp\Program.cs:line 84
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 
 

Comment by Mennan Kara [ 30/Mar/12 ]

public class OperationLog 
{
    public BsonObjectId _id { get; set; }
    public DateTime TimeCreated { get; set; }
    public string Area { get; set; }
    public string Controller { get; set; }
    public string Action { get; set; }
    public string Operation { get; set; }
}

            var server = MongoServer.Create("mongodb://localhost");
            var database = server.GetDatabase("applogs");
            if (!database.CollectionExists("OperationLog"))
            {
                database.CreateCollection("OperationLog");
            }
            var collection = database.GetCollection<OperationLog>("OperationLog");
 
            var noproblem = collection.AsQueryable<OperationLog>().Where(a => a.Area == "admin").ToList(); //This line works without a problem
            var problem = collection.AsQueryable<OperationLog>().Where(a => a.Area.ToLower() == "admin").ToList(); //This is where the exception occurs

System.ArgumentException was unhandled
  HResult=-2147024809
  Message=Unsupported where clause: (a.Area.ToLower() == "Admin").
  Source=MongoDB.Driver
  StackTrace:
       at MongoDB.Driver.Linq.SelectQuery.BuildQuery(Expression expression) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 784
       at MongoDB.Driver.Linq.SelectQuery.BuildQuery() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 113
       at MongoDB.Driver.Linq.SelectQuery.Execute() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 122
       at MongoDB.Driver.Linq.MongoQueryProvider.Execute(Expression expression) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\MongoQueryProvider.cs:line 147
       at MongoDB.Driver.Linq.MongoQueryable`1.GetEnumerator() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\MongoQueryable.cs:line 81
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
       at JetArena.ConsoleApp.Program.Main(String[] args) in D:\JetArena\JetArena.ConsoleApp\Program.cs:line 84
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

Generated at Wed Feb 07 21:36:47 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.