Wie kann ich eine möglicherweise leere Parameterliste behandeln, wenn eine benannte Abfrage in NHibernate?
-
02-10-2019 - |
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.
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:
- Wir ändern Abfrage Kategorien zu ignorieren, wenn keine solche zur Verfügung.
- Wir einen zusätzlichen Parameter ändern, um anzuzeigen ( 1 ).
- 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>();
}