[CSHARP-462] Linq doesn't support "In" clause Created: 03/May/12  Updated: 15/Nov/21  Resolved: 09/May/12

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: 1.4.2
Fix Version/s: 1.5

Type: New Feature Priority: Major - P3
Reporter: Brian Assignee: Craig Wilson
Resolution: Done Votes: 3
Labels: None
Σ Remaining Estimate: Not Specified Remaining Estimate: Not Specified
Σ Time Spent: Not Specified Time Spent: Not Specified
Σ Original Estimate: Not Specified Original Estimate: Not Specified

Issue Links:
Depends
Related
related to CSHARP-2247 Support array.Contains(value) == fals... Closed
Sub-Tasks:
Key
Summary
Type
Status
Assignee
CSHARP-2244 This does not work anymore Sub-task Closed  

 Description   

public sealed class Document
{
public string Id

{ get; set; }
public List<string> Folders { get; set; }

}
public sealed class Folder
{
public string Id

{ get; set; }

}

1. var documentFolders = documentCollection.AsQueryable().Where(x => x.Id == "document1").Select(x => x.Folders).Single();
2. var folders = folderCollection.AsQueryable().Where(x => documentFolders.Contains(x.Id)).ToArray();
3. Got this ArgumentException:
Unsupported where clause: System.Collections.Generic.List`1[System.String].Contains(x.Id).

Stack trace:

at MongoDB.Driver.Linq.SelectQuery.BuildQuery(Expression expression) in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 862
at MongoDB.Driver.Linq.SelectQuery.BuildQuery() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 123
at MongoDB.Driver.Linq.SelectQuery.Execute() in C:\work\10gen\mongodb\mongo-csharp-driver\Driver\Linq\Translators\SelectQuery.cs:line 132
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.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at DAL.MyService.MyMethod(String rId) in D:\file1.cs:line 176
at DynamicModule.ns.Wrapped_INavigationServiceRepository_364d6b61519c4b838c96d681fbc90833.<GetObjectParents_DelegateImplementation>__1(IMethodInvocation inputs, GetNextInterceptionBehaviorDelegate getNext)



 Comments   
Comment by Vijay Devappa [ 26/Feb/18 ]

It is strange, but I got this error using contains with the 2.5 nuget package

 
return (from p in collection.AsQueryable<MyClass>()
                        where p.Property1 == id &&
                              p.Property2== false &&
                              list.Contains(p.Source) == true
                        select p).ToList();

The error is:

2/26 5:32:01 PM>TID:18|CPU:34.81541|worker000000|worker000000$|Worker Service Fabric|error|DataGenerator::GenerateData()|LIN:0|********************************************************** ERROR: System.InvalidOperationException: Contains(value(System.Collections.Generic.List`1[System.Nullable`1[Locus.MongoDB.ClientWarehouse.ReportRequestSource]])) is not supported. at MongoDB.Driver.Linq.Translators.PredicateTranslator.GetFieldExpression(Expression expression) at MongoDB.Driver.Linq.Translators.PredicateTranslator.TranslateComparison(Expression variableExpression, ExpressionType operatorType, ConstantExpression constantExpression) at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node) at MongoDB.Driver.Linq.Translators.PredicateTranslator.TranslateAndAlso(BinaryExpression node) at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node) at MongoDB.Driver.Linq.Translators.PredicateTranslator.Translate(Expression node, IBsonSerializerRegistry serializerRegistry) at MongoDB.Driver.Linq.Translators.QueryableTranslator.TranslateWhere(WhereExpression node) at MongoDB.Driver.Linq.Translators.QueryableTranslator.TranslatePipeline(PipelineExpression node) at MongoDB.Driver.Linq.Translators.QueryableTranslator.Translate(Expression node, IBsonSerializerRegistry serializerRegistry, ExpressionTranslationOptions translationOptions) at MongoDB.Driver.Linq.MongoQueryProviderImpl`1.Execute(Expression expression) at MongoDB.Driver.Linq.MongoQueryableImpl`2.GetEnumerator() at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at

Comment by Craig Wilson [ 09/May/12 ]

This has been merged to master.

Comment by Craig Wilson [ 09/May/12 ]

That is a good idea. However, an Intersection produces another set, not a boolean value. Doing this would violate the intention of the Intersect method. In addition, the compiler wouldn't like this.

One possibility would be to use it in conjunction with the Any method; (c => c.List.Intersect(local).Any()) or (c => local.Intersect(c.List).Any(). We will talk about doing this, but this is a lot of work and would be difficult to document.

Comment by Gautier [ 09/May/12 ]

Thanks for your reactiveness

http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24in
"The target field's value can also be an array; if so then the document matches if any of the elements of the array's value matches any of the $in field's values"

Maybe this can be implemented in the Intersect linq method. Not really a "Contains" method, but close.
What do you think ?

Comment by Craig Wilson [ 06/May/12 ]

Thanks for your enthusiasm. This will be implemented for release 1.5 and will support both the Enumerable.Contains extension method invoked upon a local constant as well as the Contains method of ICollection<T> invoked upon a local constant. Let me know if there are any more "Contains" methods that should be utilized.

Comment by Brian [ 06/May/12 ]

There is an other problem - when you update mongo driver from 1.3 version up to the 1.4 version all your queries with "Contains" must be verified. There would not any compile-time exceptions. Just your query will fail in run-time. That was heppened with my project. I spend some time to check each query because in my DAL are two types of queries: mongo queries and linq-to-object, so i must check where I shoud set "In" and where must be "Contains".

Comment by Alexander Nagy [ 05/May/12 ]

+1 for Contains over In; Contains is a standard part of .Net via ICollection<T> whereas In is not.

Comment by Gautier [ 04/May/12 ]

And to use .In() (like other Linq To MongoDb extension methods), It is necessary to reference the MongoDb Driver dll outside of the database access layer.
I think supporting collection.Contains() method would allow a better abstraction level by allowing this functionnality to be accessible by code using the standard linq provider interface.

Comment by Ryan Hoffman [ 04/May/12 ]

@Robert - I think the driver should support either way (or, if anything using .Contains() and not .In). All other LINQ providers that I have used (Objects, SQL, EF, and NHibernate) have done "in" queries with .Contains().

I have just converted several NHibernate LINQ queries to MongoDB LINQ queries, and this is one inconsistency. It is not a big deal to change it to use the .In extension method provided by the driver, however I believe this should be done consistently with other LINQ implementations.

Comment by Brian [ 03/May/12 ]

I'm sorry because of my bug is that only that I don't know how use that library properly.
I was confussed because all linq providers I worked with do it like "collection.Contains(variable)" so I don't think that way as you said.

Comment by Robert Stam [ 03/May/12 ]

Have you tried:

Where(x => x.Id.In(documentFolders))

Perhaps we should support either way?

Comment by Brian [ 03/May/12 ]

FluentMongo supported this

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