2009-06-23 2 views
31

Я использую NHibernate и вызова хранимой процедуры с помощью именованного запроса:Как можно ввести значения типа NULL с нулевым значением в NHibernate с параметрами IQuery?

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

Многие из параметров хранимой процедуры намеренно обнуляемым - это не может быть изменен.

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>(); 

К сожалению, NHibernate не предоставляет никаких SetXyz() методы обнуляемых типов значений, так что я пытался добавить некоторые методы расширения для компенсации:

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); 
     } 
    } 
} 

Я пробовал различные версии этих, но не работают. Код выше завершается с ошибкой:

System.ArgumentNullException : A type specific Set(position, val) should be called because the Type can not be guessed from a null value. 

Я также попытался просто не установить параметр, но NHibernate требует, чтобы каждый параметр, который нужно установить. Я пробовал использовать как позиционные, так и именованные версии с одинаковыми результатами.

Есть ли способ присвоить нулевые значения значения типизированных параметров в NHibernate с именованными запросами?

ответ

50

ОК, выясняется, что на SetParameter есть некоторые переопределения, которые позволяют явно задавать тип. Например:

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

Полные методы расширения (только для Int32 и DateTime) теперь:

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

Спасибо за это, помогите мне :) – RhysC

+3

Если вернуть объект запроса из методов, которые вы также получаете цепной правильно, например: общественности статической IQuery SetDateTime (... ... Retrun запроса; –

+0

Solid расширения ! –

3

Полные методы расширения (для Int32 и только DateTime) с цепочкой теперь:

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

Спасибо, rbrock, за это дополнение к расширениям выше. Это именно то, что мне нужно. :) –

10

Другой способ сделать это:

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

И так далее ...

Обратите внимание на символ ?, который делает примитивный тип нулевым.