Comment puis-je gérer un paramètre qui peut être vide liste lorsque vous utilisez une requête nommée dans NHibernate?

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

Question

Je vais avoir des questions sur la manipulation d'une situation dans laquelle une liste des paramètres envoyés à une requête nommée dans NHibernate est vide.

Ceci est un exemple de ma situation:

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

Ceci est la méthode qui est appelée:

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

Cependant, quand je passe une liste vide à la méthode, je reçois cette erreur:

  

System.NullReferenceException:. Référence d'objet non définie à une instance d'un objet

     

trace de pile du serveur:

     

à NHibernate.Engine.TypedValue..ctor (type itype, la valeur de l'objet, EntityMode EntityMode) dans C: \ jonctions de BS \ 3rdParty \ NHibernate.2.1.2.GA-src \ src \ Hibernate \ Engine \ TypedValue. cs: ligne 25

     

à NHibernate.Impl.AbstractQueryImpl.SetParameterList (nom String, vals ICollection, le type itype) dans C: \ jonctions \ BS \ 3rdparty \ NHibernate.2.1.2.GA-src \ src \ Hibernate \ Impl \ AbstractQueryImpl.cs : ligne 647

     

à NHibernate.Impl.AbstractQueryImpl.SetParameterList (nom String, vals ICollection) dans C: \ jonctions de BS \ 3rdParty \ NHibernate.2.1.2.GA-src \ src \ Hibernate \ Impl \ AbstractQueryImpl.cs: ligne 666

     

à MyProject.Dao.MyClassDao.FilterByCategoryID (List`1 categoryIDs) dans MyClassDao.cs: ligne 50

Quelle serait la meilleure façon de résoudre ce problème? S'il vous plaît noter que la requête du nom est bien sûr beaucoup plus compliqué que celui présenté ci-dessus, donc je voudrais éviter la copier dans une seconde version qui n'utilise pas la liste des paramètres.

Était-ce utile?

La solution

Je viens face à la même question, donc je si je dois partager la solution:

Modifier votre requête à:

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

Et le code:

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

Explication:

  1. Nous modifier une requête d'ignorer les catégories lorsqu'aucune telles disponibles.
  2. Nous modifier un paramètre supplémentaire pour indiquer ( 1 ).
  3. Nous ajoutons ID aléatoire qui est jamais utilisée. Juste pour vous assurer que la instruction SQL est valide.

Ainsi, cette façon vous pouvez garder votre requête complexe et il suffit d'ajouter des paramètres supplémentaires à elle.

inconvénient évident est que ce paramètre passe inutile.

Mais il fait le travail.

Autres conseils

Je crois que vous pouvez éviter cette erreur en utilisant la Cast de .NET

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

Cela devrait retourner une liste vide, pas une exception.

test si la liste est vide et faire autre chose. dans cette requête particulière que vous voulez tous les MyClassBE qui ne sont pas dans la catégorie ids qui signifie tous:

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>();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top