Pergunta

When attempting to execute the following query on a ravendb

RavenSession.Query<R>().Any( x => DateTime.Now.Subtract( x.Submitted).TotalSeconds < 61)

an argument exception ("Could not understand expression") is thrown.

When this code is rewritten as

RavenSession.Query<R>().Any( IsSpam())

Where IsSpam is defined as:

protected Func<R, bool> IsSpam()
    {
        return r => DateTime.Now.Subtract(r.Submitted).TotalSeconds < 61;
    }

the code executes without a hitch. What is the difference in execution between the two queries?

Foi útil?

Solução

You cannot do a query like that in RavenDB. And the IsSpam method is probably doing something you are not expecting. The problem with your query is that you require us to do computation to answer it. That means that we can't optimize the query to an index seek. We don't allow such queries.

Instead, use this query:

var cutoff = DateTime.Now + TimeSpan.FromSeconds(61);

RavenSession.Query<R>.Where(x=>x.Submitted > cutoff).ToList();

Outras dicas

Expression tree parsing gets to be a complex thing, and I'm not really sure EXACTLY what's going on, although I'm not sure your posted code is exactly right as in the IsSpam() implementation, I'm not really sure how the r parameter would get in there, as it's written now.

It might have to do with the closure created in the first example and how external values could leak into it, while the second example as a Func is more explicit which wouldn't allow those crazy closure things to happen.

Regardless, the point of Raven's LINQ provider is to take the expression tree provided and ship it to the server and have the server able to convert it into Lucene query syntax. Like all abstractions, it leaks, so not everything is possible, but generally simpler things are going to work better than complex or roundabout things.

Instead of using the DateTime's Subtract method, it might work better to use standard operators:

RavenSession.Query<R>().Any(x => (DateTime.Now - x.Submitted).TotalSeconds < 61)

The expression tree created by that would be much different (and probably easier to parse) than your first one, I would expect.

Also, I have to add, be careful using DateTime.Now in your queries. The value will obviously be different every single time you run the query, so you will never be able to take advantage of the Raven client's ability to cache results.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top