4

我在处理发送到 NHibernate 中的命名查询的参数列表为空的情况时遇到问题。

这是我的情况的一个例子:

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

这是被调用的方法:

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

但是,当我将一个空列表传递给该方法时,我收到此错误:

System.NullReferenceException :对象引用未设置为对象的实例。

服务器堆栈跟踪:

在 C:\junctions\BS\3rdParty\NHibernate.2.1.2.GA-src\src\NHibernate\Engine\TypedValue.cs 中的 NHibernate.Engine.TypedValue..ctor(IType type, Object value, EntityMode entityMode): 行25

在 C:\junctions\BS\3rdParty\NHibernate.2.1.2.GA-src\src\NHibernate\Impl\AbstractQueryImpl.cs 中的 NHibernate.Impl.AbstractQueryImpl.SetParameterList(String name, ICollection vals, IType type):第 647 行

在 C:\junctions\BS\3rdParty\NHibernate.2.1.2.GA-src\src\NHibernate\Impl\AbstractQueryImpl.cs 中的 NHibernate.Impl.AbstractQueryImpl.SetParameterList(String name, ICollection vals):第 666 行

在 MyClassDao.cs 中的 MyProject.Dao.MyClassDao.FilterByCategoryID(List`1 categoryIDs):第 50 行

解决这个问题的最佳方法是什么?请注意,命名查询当然比上面介绍的要复杂得多,所以我想避免将它复制到不使用参数列表的第二个版本。

4

3 回答 3

3

我刚刚遇到了同样的问题,所以我虽然需要分享解决方案:

将您的查询修改为:

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

和代码:

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

解释:

  1. 当没有可用的类别时,我们修改查询以忽略类别。
  2. 我们修改了一个附加参数以指示 ( 1 )。
  3. 我们添加了从未使用过的随机 ID。只是为了确保IN SQL 语句有效。

因此,通过这种方式,您可以保留复杂的查询,只需向其中添加额外的参数。

明显的缺点是它传递了不必要的参数。

但它完成了这项工作。

于 2011-02-22T01:15:48.713 回答
0

我相信您可以通过使用 .NET 来避免该错误Cast

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

那应该返回一个空列表,而不是异常。

于 2010-09-13T13:05:23.567 回答
0

测试列表是否为空并执行其他操作。在此特定查询中,您想要所有不在类别 ID 中的 MyClassBE,这意味着所有这些:

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>();
}
于 2010-09-13T13:19:56.710 回答