¿Cómo se pueden establecer los valores escritos de valores anulables de C # en los parámetros de NHibernate denominados IQuery?
-
06-07-2019 - |
Pregunta
Estoy usando NHibernate y llamo a un procedimiento almacenado a través de una consulta con nombre:
<sql-query name="SearchStuff" read-only="true" cacheable="true">
<return class="ResultEntity" />
EXEC [SearchStuff] ?, ?, ? </sql-query>
Muchos de los parámetros de procedimientos almacenados son anulables deliberadamente; esto no se puede cambiar.
El C #:
IQuery listQuery = this.Session.GetNamedQuery("SearchStuff");
listQuery.SetInt32(0, param1);
listQuery.SetDateTime(1, param2);
listQuery.SetString(2, param3);
IList<ResultEntity> results = listQuery.List<ResultEntity>();
Desafortunadamente, NHibernate no proporciona ningún método SetXyz () para los tipos de valores anulables, así que intenté agregar algunos métodos de extensión para compensar:
public static class QueryExtensions
{
public static void SetInt32(this IQuery query, int position, int? val)
{
if (val.HasValue)
{
query.SetInt32(position, val.Value);
}
else
{
query.SetParameter(position, null);
}
}
public static void SetInt32(this IQuery query, string name, int? val)
{
if (val.HasValue)
{
query.SetInt32(name, val.Value);
}
else
{
query.SetParameter(name, null);
}
}
public static void SetDateTime(this IQuery query, int position, DateTime? val)
{
if (val.HasValue)
{
query.SetDateTime(position, val.Value);
}
else
{
query.SetParameter(position, null);
}
}
public static void SetDateTime(this IQuery query, string name, DateTime? val)
{
if (val.HasValue)
{
query.SetDateTime(name, val.Value);
}
else
{
query.SetParameter(name, null);
}
}
}
He probado varias versiones de estos pero ninguno funciona. El código anterior falla con el error:
System.ArgumentNullException : A type specific Set(position, val) should be called because the Type can not be guessed from a null value.
También intenté simplemente no configurar el parámetro, pero NHibernate requiere que se configuren todos los parámetros. Intenté usar versiones posicionales y con nombre con los mismos resultados.
¿Hay alguna forma de asignar valores nulos a los parámetros escritos en NHibernate?
Solución
OK, resulta que hay algunas anulaciones en SetParameter que permiten que el tipo se establezca explícitamente. Por ejemplo:
query.SetParameter(position, null, NHibernateUtil.Int32);
Los métodos de extensión completa (solo para Int32 y DateTime) ahora son:
public static class QueryExtensions
{
public static void SetInt32(this IQuery query, int position, int? val)
{
if (val.HasValue)
{
query.SetInt32(position, val.Value);
}
else
{
query.SetParameter(position, null, NHibernateUtil.Int32);
}
}
public static void SetInt32(this IQuery query, string name, int? val)
{
if (val.HasValue)
{
query.SetInt32(name, val.Value);
}
else
{
query.SetParameter(name, null, NHibernateUtil.Int32);
}
}
public static void SetDateTime(this IQuery query, int position, DateTime? val)
{
if (val.HasValue)
{
query.SetDateTime(position, val.Value);
}
else
{
query.SetParameter(position, null, NHibernateUtil.DateTime);
}
}
public static void SetDateTime(this IQuery query, string name, DateTime? val)
{
if (val.HasValue)
{
query.SetDateTime(name, val.Value);
}
else
{
query.SetParameter(name, null, NHibernateUtil.DateTime);
}
}
}
Otros consejos
Otra forma de lograrlo es:
query.SetParameter<int?>(0, null);
query.SetParameter<DateTime?>(1, null);
...
Y así sucesivamente ...
Observe el símbolo ?
que hace que el tipo primitivo sea anulable.
Los métodos de extensión completa (solo para Int32 y DateTime) con encadenamiento ahora son:
public static class QueryExtensions
{
public static IQuery SetInt32(this IQuery __query, int __position, int? __val)
{
var _query = __val.HasValue ? __query.SetInt32(__position, __val.Value) : __query.SetParameter(__position, null, NHibernateUtil.Int32);
return _query;
}
public static IQuery SetInt32(this IQuery __query, string __name, int? __val)
{
var _query = __val.HasValue ? __query.SetInt32(__name, __val.Value) : __query.SetParameter(__name, null, NHibernateUtil.Int32);
return _query;
}
public static IQuery SetDateTime(this IQuery __query, int __position, DateTime? __val)
{
var _query = __val.HasValue ? __query.SetDateTime(__position, __val.Value) : __query.SetParameter(__position, null, NHibernateUtil.DateTime);
return _query;
}
public static IQuery SetDateTime(this IQuery __query, string __name, DateTime? __val)
{
var _query = __val.HasValue ? __query.SetDateTime(__name, __val.Value) : __query.SetParameter(__name, null, NHibernateUtil.DateTime);
return _query;
}
}