Naftis Naftis - 1 year ago 299
C# Question

MongoDB C# - LINQ Contains against a string array throws ArgumentException

I'm new to MongoDB so this might be a naive question, yet I have not found any relevant/up to date information by googling around: I am trying to use the MongoDB C# driver (version 2.2.4) to compose a LINQ-based query, one piece at a time, from a received

POCO object, like this:

IQueryable<BsonDocument> parts = collection.AsQueryable();
if (filter.Name != null)
parts = parts.Where(d => d["Name"].Equals(filter.Name));
// ... etc; I'll then call ToList() to get results ...

Now, one of my
properties is a string array, meaning that I should match any document whose field
(a string property in the MongoDB document) is equal to any of the strings in the array (like MongoDB native

To this end, I tried with
(the special case for a 1-sized array is just an optimization):

if (filter.Vendors != null && filter.Vendors.Length > 0)
parts = filter.Vendors.Length == 1
? parts.Where(d => d["Vendor"].Equals(filter.Vendors[0]))
: parts.Where(d => filter.Vendors.Contains(d["Vendor"].AsString));

This compiles, but throws an
: "Expression of type 'MongoDB.Bson.BsonValue' cannot be used for parameter of type 'System.String' of method 'Boolean Contains[String](System.Collections.Generic.IEnumerable`1[System.String], System.String)'".

Looking at, there is nothing about
; yet, from
it seems that the driver should now be capable of handling that method.

BTW, the same happens if I slightly change the code to:

parts.Where(d => filter.Vendors.Any(s=> d["Vendor"].Equals(s)));

which does not involve
at all. The exception message complains about not being able to use
, yet that
is right a
. Could anyone suggest a solution?

Answer Source

The exception messages dance around the idea of fully embracing BsonValue to let mongo handle the types instead of trying to cast to string. I got it to work having Vendors as type List<BsonValue>.

class Filter
        public List<BsonValue> Vendors { get; set; }


var list = parts.Where(d => filter.Vendors.Contains(d["Vendor"]));
foreach (var document in list)

Another alternative is to map your documents to a C# class instead of using BsonDocument as the collection type.

class MyDocument
    public ObjectId Id { get; set; }
    public string Name { get; set; }
    public string Vendor { get; set; }
var collection = db.GetCollection <MyDocument> ("parts");
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download