Как можно задать типизированные значения C # Nullable для именованных параметров IQuery NHibernate? - PullRequest
31 голосов
/ 23 июня 2009

Я использую NHibernate и вызываю хранимую процедуру с помощью именованного запроса:

<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 () для типов значений Nullable, поэтому я попытался добавить некоторые методы расширения для компенсации:

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?

Ответы [ 3 ]

52 голосов
/ 23 июня 2009

ОК, оказывается, есть некоторые переопределения в 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);
        }
    }
}
11 голосов
/ 04 июля 2013

Еще один способ сделать это:

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

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

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

3 голосов
/ 26 марта 2012

Методы полного расширения (только для 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;
    }
}
...