2009-06-23 7 views
31

Sto usando NHibernate e chiamando una stored procedure tramite una query denominata:In che modo i valori digitati del valore N C# possono essere impostati su NHibernate con i parametri IQuery?

<sql-query name="SearchStuff" read-only="true" cacheable="true"> 
    <return class="ResultEntity" /> 
    EXEC [SearchStuff] ?, ?, ? </sql-query> 

Molti dei parametri di stored procedure sono deliberatamente annullabile - 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>(); 

Purtroppo, NHibernate non fornisce alcuna SetXyz() metodi per i tipi di valore nullable così 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 questi, ma nessuno funziona. Il codice di cui sopra non riesce 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 non impostare il parametro, ma NHibernate richiede tutti i parametri da impostare. Ho provato ad usare entrambe le versioni posizionale e denominata con gli stessi risultati.

C'è un modo per assegnare valori nulli ai parametri digitati di valore in query denominate NHibernate?

risposta

50

OK, si scopre che esistono alcuni override su SetParameter che consentono di impostare il tipo in modo esplicito. Ad esempio:

query.SetParameter(position, null, NHibernateUtil.Int32); 

I metodi di estensione completi (per Int32 e DateTime solo) 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); 
     } 
    } 
} 
+0

Grazie per questo, aiutami :) – RhysC

+3

Se si restituisce l'oggetto query dai metodi si ottiene anche il corretto, ad esempio il concatenamento: public static IQuery SetDateTime (... ... interrogazione retrun; –

+0

estensioni solide ! –

3

I metodi di estensione completi (per Int32 e solo DateTime) con concatenamento vengono 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; 
    } 
} 
+0

Grazie, rbrock, per questa aggiunta alle estensioni di cui sopra. Questo è esattamente ciò di cui avevo bisogno. :) –

10

Un altro modo per realizzarlo è:

query.SetParameter<int?>(0, null); 
query.SetParameter<DateTime?>(1, null); 
... 

E così via ...

Si noti il ​​simbolo ? che rende nullable il tipo primitivo.