Better exception message for Invalid handling of empty parameter lists
Description
Environment
Activity
Kurt Harriger November 16, 2009 at 12:20 PM
I too ran into this issue today, but unlike above I the in clause was an part of an OR clause so for example
@"FROM Opportunity o WHERE Name = :name OR Id in (:foo)")
In this case I still needed to execute the query against but without the in clause when :foo is an empty list.
Since SetParameterList throws an error if the parameter list is empty you now need to build the hql dynamically which just is ugly and you will get an error if you try to add :foo to the parameter list if its not in the query which leads to more ugly if statements.
SQL may not allow you to specify an empty IN clause however since it would be nicer if it HQL on empty list would translated to 1=0 since the result if the expression would always be false.
Fabio Maulo July 31, 2008 at 7:09 AM
This is not a bug but it is a user fault.
You can't set an empty parameter list.
Here's my code:
CurrentSession.CreateQuery(
@"FROM Opportunity o WHERE Id in (:foo)")
.SetParameterList("foo", new long[] {})
.List<Opportunity>();
The Id column is a 64 bit integer, mapped correctly, and results in a NullReferenceException in NHibernate. When I call SetParameterList, here's what happens:
AbstractQueryImpl.SetParameterList():
if (vals.Count == 0)
SetParameterList(name, vals, null)
Then it tries to create a TypedValue with a null type, and this is where the error happens in the TypedValue constructor since type is null:
if (!type.IsCollectionType && values != null)
Workaround is simple, I can explicity set the type, but there's still a bug here, that's why I call it a workaround. The first SetParameterList function calling the second one with a null type parameter seems explicit and deliberate, like it's expecting the following code to deal with null types, which it doesn't. And even with an empty collection, the type can be guessed most if not all of the time by the type of the column (Id in my example), or you can check that if the parameter is array, then you can simply get the item type without any elements in it, or if it's a generic collection, then again, there's an easy way with reflection to get the item type. And if none of that works, then an appropriate NHibernate exception should be thrown, saying that "the type cannot be determined and should be explicitly set", you shouldn't let NullReferenceException's occur just like that.