Reputation: 4509
I have problem with the NHibernate's second level cache. When I use query:
var items1 = Session.Query<Row>()
.Cacheable();
.Fetch(x => x.Field)
.OrderBy(x => x.Field.Value)
.ToList();
Everything is fine - the query is cached. But when I want to use Dynamic Linq (a link):
var items2 = Session.Query<Row>()
.Cacheable();
.Fetch(x => x.Field)
.OrderBy("Field.Value")
.ToList();
The query is not cached. Interesting thing is that, when I delete code line:
.Fetch(x => x.Field)
caching works again. So the problem is with using Fetch and dynamic linq OrderBy methods together.
EDIT:
When I try do debug NH code (QueryKey class), debugger tells me that these two queries do not have the same ResultTransformer (and deeper: a listTransformation private instance).
Any ideas?
Chris
Upvotes: 3
Views: 1969
Reputation: 4509
Ok, I know what is the reason.
Dynamic Linq doesn't use Parameter Names in Linq Expressions. E.g. if I want to sort using lambda statemant, I write:
query.OrderBy(item => item.Name)
Above we see an item
lambda parameter name.
When I use Dynamic linq:
query.OrderBy("Name")
in the result Queryable the lambda parameter in OrderBy mehod has no name (like item
written above). We can illustrate the result like this:
query.OrderBy( => .Name)
And now, when NHibernate is decoding that Queryable expression and finds there an expression parameter that has no name, NH gives it a random name using GUID class. So every ordering using dynamic linq produces a Queryable Expression that has inconstant lambda parameter. This is the reason why NHibernate thinks that: query.OrderBy("Name")
and query.OrderBy("Name")
are not the same - they have another lamda parameters generated every time from scratch.
SOLUTION
If you want to fix it, you have to modify Dynamic Linq library.
In method ExpressionParser.ProcessParameters
change line:
if (parameters.Length == 1 && String.IsNullOrEmpty(parameters[0].Name))
to:
if (parameters.Length == 1 && (parameters[0].Name == "it" || String.IsNullOrEmpty(parameters[0].Name)))
In method DynamicQueryable.OrderBy
change line:
Expression.Parameter(source.ElementType, "")
to:
Expression.Parameter(source.ElementType, "it")
Now, query.OrderBy("Name")
will produce query.OrderBy(it => it.Name)
.
Cheers!
Upvotes: 2