Как я могу обработать возможно пустой список параметров при использовании именованного запроса в NHibernate?

StackOverflow https://stackoverflow.com/questions/3700392

Вопрос

У меня возникли проблемы при обработке ситуации, когда список параметров, отправленных в именованный запрос в NHibernate, пуст.

Это пример моей ситуации:

<sql-query name="MyClass_FilterByCategoryID">
    <return alias="MyClass" class="MyProject.BusinessEntities.MyClassBE"/>
    <![CDATA[
    SELECT DISTINCT MyClass.*
    FROM MyClassTable MyClass
    WHERE 1 = 1
            AND MyClassTable.CategoryID NOT IN (:categoryIDs) 
    ]]>
</sql-query>

Это метод, который вызывается:

public IList<MyClassBE> FilterByCategoryID(List<String> categoryIDs)
{
    return session.GetNamedQuery("MyClass_FilterByCategoryID")
        .SetParameterList("categoryIDs", categoryIDs)
        .List<MyClassBE>();
}

Однако, когда я передаю методу пустой список, я получаю эту ошибку:

Исключение System.NullReferenceException :Ссылка на объект не задана для экземпляра объекта.

Трассировка стека сервера:

в NHibernate.Движок.Типизированное значение..ctor(тип IType, значение объекта, EntityMode entityMode entityMode) в C:\junctions\BS\3rdParty Hibernate.2.1.2.GA-src\src Hibernate\Engine ypedValue.cs:строка 25

в NHibernate.Impl.AbstractQueryImpl.SetParameterList(имя строки, значения ICollection, тип IType) в C:\junctions\BS\3rdParty Hibernate.2.1.2.GA-src\src Hibernate\Impl\AbstractQueryImpl.cs:строка 647

в NHibernate.Impl.AbstractQueryImpl.SetParameterList(имя строки, значения ICollection) в C:\junctions\BS\3rdParty Hibernate.2.1.2.GA-src\src Hibernate\Impl\AbstractQueryImpl.cs:строка 666

в MyProject.Dao.MyClassDao.FilterByCategoryID(список`1 categoryIDs) в MyClassDao.cs:строка 50

Каков был бы наилучший способ решить эту проблему?Пожалуйста, обратите внимание, что именованный запрос, конечно, намного сложнее, чем представленный выше, поэтому я бы не хотел копировать его во вторую версию, которая не использует список параметров.

Это было полезно?

Решение

Я только что столкнулся с такой же проблемой, поэтому решил, что мне нужно поделиться решением:

Измените свой запрос следующим образом:

<sql-query name="MyClass_FilterByCategoryID">
    <return alias="MyClass" class="MyProject.BusinessEntities.MyClassBE"/>
    <![CDATA[
    SELECT DISTINCT MyClass.*
    FROM MyClassTable MyClass
    WHERE 
            (
              :hasCatogories=0
              or (:hasCatogories=1 and MyClassTable.CategoryID NOT IN (:categoryIDs) )
            )
    ]]>
</sql-query>

И код для:

public IList<MyClassBE> FilterByCategoryID(List<String> categoryIDs)
{
    return session.GetNamedQuery("MyClass_FilterByCategoryID")
        .SetIn32("hasCatogories", categoryIDs.Any() ? 1 : 0)
        .SetParameterList("categoryIDs", categoryIDs.Any() ? categoryIDs : new [] {"fake-non-existing-id"})
        .List<MyClassBE>();
}

Объяснение:

  1. Мы изменяем запрос, чтобы игнорировать категории, если таковые отсутствуют.
  2. Мы изменяем дополнительный параметр, чтобы указать (1).
  3. Мы добавляем случайный идентификатор, который никогда не используется.Просто для того, чтобы убедиться, что В Оператор SQL является допустимым.

Таким образом, вы можете сохранить свой сложный запрос и просто добавить к нему дополнительные параметры.

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

Но это делает свое дело.

Другие советы

Я полагаю, вы можете избежать этой ошибки, используя .NET's Cast

return session.GetNamedQuery("MyClass_FilterByCategoryID")
    .SetParameterList("categoryIDs", categoryIDs)
    .List().Cast<MyClassBE>();

Это должно возвращать пустой список, а не исключение.

проверьте, пуст ли список, и сделайте что-нибудь еще.в этом конкретном запросе вам нужны все MyClassBE, которых нет в идентификаторах категорий, что означает их все:

public IList<MyClassBE> FilterByCategoryID(List<String> categoryIDs)
{
    if (categoryIDs.Count > 0)
        return session.GetNamedQuery("MyClass_FilterByCategoryID")
            .SetParameterList("categoryIDs", categoryIDs)
            .List<MyClassBE>();
    else
        return session.CreateQuery("from MyClassBe").List<MyClassBE>();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top