Как я могу обработать возможно пустой параметр List при использовании именованного запроса в NHibernate? - PullRequest
4 голосов
/ 13 сентября 2010

У меня проблемы с обработкой ситуации, когда список параметров, отправляемых на именованный запрос в 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.Engine.TypedValue..ctor (тип IType, значение объекта, EntityMode entityMode) в C: \ junctions \ BS \ 3rdParty \ NHibernate.2.1.2.GA-src \ src \ NHibernate \ Engine \ TypedValue. CS: строка 25

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

в NHibernate.

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

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

Ответы [ 3 ]

3 голосов
/ 22 февраля 2011

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

Измените ваш запрос на:

<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 IN является допустимым.

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

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

Но это делает работу.

0 голосов
/ 13 сентября 2010

проверить, если список пуст, и сделать что-нибудь еще.в этом конкретном запросе вы хотите, чтобы все 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>();
}
0 голосов
/ 13 сентября 2010

Я полагаю, что вы можете избежать этой ошибки, используя .NET Cast <pre>return session.GetNamedQuery("MyClass_FilterByCategoryID") .SetParameterList("categoryIDs", categoryIDs) .List().Cast<MyClassBE>();

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

...