在使用NHIBERNATE中使用命名查询时,如何处理可能的空参数列表?
-
02-10-2019 - |
题
我在处理一个情况下遇到问题,即发送到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 src src src nhibernate nhibernate nhibernate nhibernate prient typedvalue.cs:linepedvalue.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.1.2.ctor.ctor..ctor .. 25
在c: junctions bs bs 3rdparty nhibernate.2.1.2.ga-src src src src src src nhibernate nhibernate nhibernate nhibernate nhibernate nhibernate simpququereimpl.cs:lincequeryimpl.cc:
在c: junctions bs 3rdparty nhibernate.2.1.2.ga-src src src src src nhibernate nhibernate nhibernate nhibernate nhibernate nhibrnate nhibrnate nhibqueryimpl.cs:bs nhibernate.impl.impl.impl.stractqueryimpl.setParameterList(字符串名称,Icollection Vals)中
在myclassdao.cs中的myproject.dao.myclassdao.myclassdao.filterbycategoryid(list`1 categoryIds):50行
解决这个问题的最佳方法是什么?请注意,命名的查询当然比上面提出的查询要复杂得多,因此我想避免将其复制到不使用参数列表的第二个版本。
解决方案
我刚刚面对同样的问题,所以我需要分享解决方案:
将查询修改为:
<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).
- 我们添加从未使用的随机ID。只是为了确保 在 SQL语句有效。
因此,您可以保留复杂的查询,只需在其中添加其他参数即可。
显而易见的缺点是它传递了不必要的参数。
但是它可以完成工作。
其他提示
我相信您可以通过使用.NET避免该错误 Cast
return session.GetNamedQuery("MyClass_FilterByCategoryID")
.SetParameterList("categoryIDs", categoryIDs)
.List().Cast<MyClassBE>();
那应该返回一个空列表,而不是例外。
测试列表是否为空并做其他事情。在此特定查询中,您希望所有不在类别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>();
}