Wie kann ich eine möglicherweise leere Parameterliste behandeln, wenn eine benannte Abfrage in NHibernate?

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

Frage

Ich habe Probleme auf eine Situation Umgang mit dem eine Liste von Parametern zu einer benannten Abfrage in NHibernate gesendet leer ist.

Dies ist ein Beispiel für meine 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>

Dies ist die Methode, die aufgerufen wird:

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

Allerdings, wenn ich eine leere Liste an die Methode übergeben, bekomme ich diesen Fehler:

System.NullReferenceException:. Objektverweis nicht auf eine Instanz eines Objekts festgelegt

Server-Stack-Trace:

bei NHibernate.Engine.TypedValue..ctor (IType Typ, Objektwert, EntityMode entityMode) in C: \ Kreuzungen \ BS \ 3rdParty \ NHibernate.2.1.2.GA-src \ src \ NHibernate \ Engine \ TypedValue. cs: Zeile 25

bei NHibernate.Impl.AbstractQueryImpl.SetParameterList (String name, ICollection vals, IType Typ) in C: \ Kreuzungen \ BS \ 3rdParty \ NHibernate.2.1.2.GA-src \ src \ NHibernate \ Impl \ AbstractQueryImpl.cs : line 647

bei NHibernate.Impl.AbstractQueryImpl.SetParameterList (String name, ICollection vals) in C: \ Kreuzungen \ BS \ 3rdParty \ NHibernate.2.1.2.GA-src \ src \ NHibernate \ Impl \ AbstractQueryImpl.cs: line 666

bei MyProject.Dao.MyClassDao.FilterByCategoryID (List`1 CategoryIDs) in MyClassDao.cs: Linie 50

Was wäre der beste Weg, dies zu lösen? Bitte beachten Sie, dass die benannte Abfrage ist natürlich viel komplizierter als die oben dargestellt, so würde ich es auf eine zweite Version zu vermeiden, wie das Kopieren, die nicht die Parameterliste nicht verwendet.

War es hilfreich?

Lösung

Ich habe gerade das gleiche Problem konfrontiert, so dachte ich, ich brauche die Lösung zu teilen:

Ändern Sie bitte Ihre Anfrage an:

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

Und der Code an:

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

Erklärung:

  1. Wir ändern Abfrage Kategorien zu ignorieren, wenn keine solche zur Verfügung.
  2. Wir einen zusätzlichen Parameter ändern, um anzuzeigen ( 1 ).
  3. Wir fügen Zufalls-ID, die nie verwendet wird. Nur um sicherzustellen, dass die in SQL-Anweisung gültig ist.

So diese Weise können Sie Ihre komplexe Abfrage halten und fügen Sie einfach zusätzliche Parameter zu.

offensichtlicher Nachteil ist, dass es nicht notwendig, Parameter übergibt.

Aber es macht den Job.

Andere Tipps

Ich glaube, Sie diesen Fehler vermeiden können von .NET Cast unter Verwendung

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

Das sollte eine leere Liste zurück, da keine Ausnahme.

Test, wenn die Liste leer ist und etwas anderes tun. in dieser speziellen Abfrage möchten Sie alle MyClassBE, die nicht in die Kategorie-IDs sind, welche alle von ihnen bedeutet:

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>();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top