Come posso gestire una lista di parametri che può essere vuoto quando si utilizza una query denominata in NHibernate?

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

Domanda

sto avendo problemi di gestione di una situazione in cui un elenco di parametri inviato a una query denominata in NHibernate è vuoto.

Questo è un esempio della mia situazione:

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

Questo è il metodo che viene chiamato:

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

Tuttavia, quando passo una lista vuota al metodo, ottengo questo errore:

  

System.NullReferenceException:. Il riferimento non impostato a un'istanza di un oggetto

     

dello stack trace Server:

     

a NHibernate.Engine.TypedValue..ctor (tipo IType, Object value, EntityMode entityMode) in C: \ giunzioni \ BS \ 3rdParty \ NHibernate.2.1.2.GA-src \ src \ NHibernate \ Engine \ TypedValue. cs: linea 25

     

a NHibernate.Impl.AbstractQueryImpl.SetParameterList (String name, vals ICollection, tipo IType) in C: \ giunzioni \ BS \ 3rdparty \ NHibernate.2.1.2.GA-src \ src \ NHibernate \ Impl \ AbstractQueryImpl.cs : linea 647

     

a NHibernate.Impl.AbstractQueryImpl.SetParameterList (String name, vals ICollection) in C: \ giunzioni \ BS \ 3rdParty \ NHibernate.2.1.2.GA-src \ src \ NHibernate \ Impl \ AbstractQueryImpl.cs: la linea 666

     

a MyProject.Dao.MyClassDao.FilterByCategoryID (List`1 categoryIDs) in MyClassDao.cs: linea 50

Quale sarebbe il modo migliore per risolvere questo problema? Si prega di notare che la query di nome è, naturalmente, molto più complicato di quello presentato in precedenza, quindi mi piacerebbe evitare di copiare a una seconda versione che non utilizza l'elenco dei parametri.

È stato utile?

Soluzione

Ho appena affrontato lo stesso problema, quindi ho anche se ho bisogno di condividere la soluzione:

Modifica la tua richiesta 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>

E il codice a:

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

Spiegazione:

  1. modificare query di ignorare le categorie in cui tale disposizione.
  2. modificare un parametro aggiuntivo per indicare ( 1 ).
  3. Aggiungiamo ID casuale che non viene mai utilizzato. Giusto per assicurarsi che il in istruzione SQL è valido.

Quindi questo modo è possibile mantenere la vostra query complessa e basta aggiungere parametri aggiuntivi ad esso.

svantaggio evidente è che si passa il parametro inutile.

Ma fa il lavoro.

Altri suggerimenti

Credo che si può evitare tale errore utilizzando Cast di .NET

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

che dovrebbe restituire un elenco vuoto, non è un'eccezione.

test se la lista è vuota e fare qualcosa di diverso. in questo particolare query che si desidera tutto il MyClassBE che non sono nei ID di categoria che significa tutti loro:

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>();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top