Come si possono impostare i valori digitati con valore nulla in C # sui parametri IQuery di NHibernate?
-
06-07-2019 - |
Domanda
Sto utilizzando NHibernate e sto chiamando una procedura memorizzata tramite una query denominata:
<sql-query name="SearchStuff" read-only="true" cacheable="true">
<return class="ResultEntity" />
EXEC [SearchStuff] ?, ?, ? </sql-query>
Molti dei parametri della procedura memorizzata sono volutamente nulli - questo non può essere modificato.
Il 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>();
Sfortunatamente, NHibernate non fornisce alcun metodo SetXyz () per tipi di valore nullable, quindi ho provato ad aggiungere alcuni metodi di estensione per compensare:
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);
}
}
}
Ho provato varie versioni di queste, ma nessuna funziona. Il codice sopra fallisce con l'errore:
System.ArgumentNullException : A type specific Set(position, val) should be called because the Type can not be guessed from a null value.
Ho anche provato semplicemente a non impostare il parametro ma NHibernate richiede che tutti i parametri siano impostati. Ho provato a utilizzare entrambe le versioni posizionali e denominate con gli stessi risultati.
Esiste un modo per assegnare valori null al valore dei parametri digitati nelle query denominate NHibernate?
Soluzione
OK, si scopre che ci sono alcune sostituzioni su SetParameter che consentono di impostare esplicitamente il tipo. Ad esempio:
query.SetParameter(position, null, NHibernateUtil.Int32);
I metodi di estensione completa (solo per Int32 e DateTime) sono ora:
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);
}
}
}
Altri suggerimenti
Un altro modo per realizzarlo è:
query.SetParameter<int?>(0, null);
query.SetParameter<DateTime?>(1, null);
...
E così via ...
Notare il simbolo ?
che rende il tipo primitivo nullable.
I metodi di estensione completa (solo per Int32 e DateTime) con concatenamento sono ora:
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;
}
}