Background:
During some recent refactoring – I was converting some old NHibernate code that was using the Criteria API to instead use Linq-to-NHibernate – I ran into a major roadblock. In my previous code – I was receiving parameters from my client regarding pagination, sorting, and filtering. Converting the pagination wasn’t too bad, then I got to the filtering and sorting…
My client (javascript) has passed me the string for the column it wants sorted. Linq wants a strongly typed function pointing to the member to sort on. I really don’t want to go write a translation layer that converts every string they could send me to a valid Linq Expression… so then I found Dynamic Linq.
Dynamic Linq:
You can find a blog about it by Scott Guthrie here: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
You can download the sample which contains the code here: http://msdn2.microsoft.com/en-us/vcsharp/bb894665.aspx
Down to the Code:
I set up a proof of concept – available here: https://github.com/jhoguet/DynamicLinq---Nhibernate-Proof-of-Concept
Filtering:
[Test]
public void ProofWhereEquals()
{
var person = _dao.GetPeople().Where("FirstName=@0", "Jon").Single();
Assert.AreEqual(expected:"Jon", actual:person.FirstName);
}
and note this gets translated all the way down to NHibernate generating the following SQLite code
not bad – how about something more realistic for a filter… LIKE
public void ProofWhereContains()
{
var person = _dao.GetPeople().Where("FirstName.Contains(@0)", "o").Single();
Assert.AreEqual(expected: "Jon", actual: person.FirstName);
}
which generated…
alright I am impressed – but surely it will break if we do a NOT
public void ProofWhereNotLike()
{
var person = _dao.GetPeople().Where("!FirstName.Contains(@0)", "o").Single();
Assert.AreEqual(expected: "Manrique", actual: person.FirstName);
}
which generated…
alright I am impressed!
But can it handle the order by problem…
public void CanOrderBy()
{
var person = _dao.GetPeople().OrderBy("FirstName descending").First();
Assert.AreEqual(expected: "Manrique", actual: person.FirstName);
}
which generated…
sweet!
At this point I was satisfied and moved on – I know I read some blogs that spoke of limited support within DynamicLinq – but it certainly covered what I needed (I vaguely remember one example LIKE ‘StartWith%’)
I did find one surprising side effect (I might argue bug).
public void WhenArgIsNullBadThingsHappen()
{
try
{
var person = _dao.GetPeople().Where("!FirstName.Contains(@0)", null).Single();
}
catch
{
//you need to check for null in your implementation
}
}
When you pass in null as the parameter you get some misleading exception
No comments:
Post a Comment