Picture of a lake in Canada

MongoDB LINQ Queries executing on the client side.

February 3, 2014 , posted under programming ASP.NET C# LINQ MongoDB infometrics

For my Final Year Project at University I have been building “Infometrics”, something I may well provide more detail on in the future. In this case the only thing you need to know about it that its a C# App written with a MongoDB backend.

Now the crux of the issue I was experiencing was that all database operations seemed to be slow, despite not having that many documents, and indexes set up.  I was getting very confused as to why MongoDB’s query profiler was showing an empty query body, and assumed it was something to do with my Expression building code. It all boiled down to the fact that the wrong .Where() method was getting called.

//Before (Works, but computed on the client side)
public List<Event> Find(Func<Event, bool> query)
{
    return _db.Events.Where(query).ToList();
}

//After (Works on the server side)
public List<Event> Find(Expression<Func<Event, bool>> query)
{
    return _db.Events.Where(query).ToList();
}

In order to work out that was the case, I fiddled around with the debugger:

public List<Event> Find(Expression<Func<Event, bool>> query)
{
    _db.Events.Where(e => e.Timestamp >= DateTime.Now.AddMinutes(-30)).ToList();

    return _db.Events.Where(query).ToList();
}

From the code above you might assume that both would be work as desired, but that is not the case, this is fact is only revealed during runtime, or by doing some further investigation with dotPeek/other decompiler.

Enumerable.ToList<Event>((IEnumerable<Event>) Queryable.Where<Event>((IQueryable<Event>) this._db.Events, (Expression<Func<Event, bool>>) (e => e.Timestamp >= DateTime.Now.AddMinutes(-30.0))));
Enumerable.ToList<Event>(Enumerable.Where<Event>((IEnumerable<Event>) this._db.Events, query));

Now with the code above (first line works, second does not) you can see that the IEnumerable.Where method is being called, whereas on the above line the IQueryable.Where method is executing. This difference is ultimately what brought me to find the fix (changing the parameter type).

Additionally during execution and stepping through areas of the C# MongoDB driver that MongoDB was just returning all of the results, and letting .NET perform the execution of the predicate.

comments powered by Disqus