¿Cómo puedo manejar una lista de parámetros posiblemente vacía cuando se utiliza una consulta con nombre en NHibernate?

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

Pregunta

Tengo problemas en el manejo de una situación en la que una lista de parámetros enviado a una consulta con nombre en NHibernate está vacía.

Este es un ejemplo de mi situación:

<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>

Este es el método que es llamada:

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

Sin embargo, cuando paso una lista vacía con el método, me sale este error:

System.NullReferenceException:. Referencia a objeto no establecida como una instancia de un objeto

seguimiento de la pila del servidor:

a NHibernate.Engine.TypedValue..ctor (tipo iType, del valor del objeto, EntityMode EntityMode) en C: \ uniones \ BS \ 3RDPARTY \ NHibernate.2.1.2.GA-src \ src \ NHibernate \ Engine \ TypedValue. cs: línea 25

a NHibernate.Impl.AbstractQueryImpl.SetParameterList (String name, Vals ICollection, tipo iType) en C: \ uniones \ BS \ 3RDPARTY \ NHibernate.2.1.2.GA-src \ src \ NHibernate \ Impl \ AbstractQueryImpl.cs : línea 647

a NHibernate.Impl.AbstractQueryImpl.SetParameterList (String name, Vals ICollection) en C: \ uniones \ BS \ 3RDPARTY \ NHibernate.2.1.2.GA-src \ src \ NHibernate \ Impl \ AbstractQueryImpl.cs: línea 666

a MyProject.Dao.MyClassDao.FilterByCategoryID (List`1 CategoryIDs) en MyClassDao.cs: línea 50

¿Cuál sería la mejor manera de resolver esto? Tenga en cuenta que la consulta con nombre, por supuesto, es mucho más complicado que el presentado anteriormente, así que me gustaría evitar copiarlo en una segunda versión que no utiliza la lista de parámetros.

¿Fue útil?

Solución

Yo sólo he enfrentado a la misma cuestión, por lo que a pesar de que necesito compartir la solución:

Modificar la consulta a:

<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>

Y el código para:

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

Explicación:

  1. modificar consulta a ignorar categorías cuando hay tal disposición.
  2. Nos modificar un parámetro adicional para indicar ( 1 ).
  3. Añadimos ID aleatorio que nunca se utiliza. Sólo para asegurarse de que el In instrucción SQL es válida.

Así de esta manera usted puede mantener su consulta compleja y sólo tiene que añadir parámetros adicionales a la misma.

desventaja obvia es que pasa parámetro innecesario.

Pero hace el trabajo.

Otros consejos

Creo que se puede evitar que el error mediante el uso de .NET Cast

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

Esto debería devolver una lista vacía, no es una excepción.

prueba si la lista está vacía y hacer otra cosa. en esta consulta en particular que desea todo el MyClassBE que no están en la categoría identificadores de lo que significa todos ellos:

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>();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top