在 NHibernate 中使用命名查询时,如何处理可能为空的参数列表?

发布于 2024-09-18 12:09:55 字数 1567 浏览 5 评论 0原文

我在处理发送到 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 中的 NHibernate.Engine.TypedValue..ctor(IType 类型、对象值、EntityModeEntityMode)。 CS:第 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 行

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

I'm having issues on handling a situation where a list of parameters sent to a named query in NHibernate is empty.

This is an example of my 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>

This is the method that gets called:

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

However, when I pass an empty List to the method, I get this error:

System.NullReferenceException : Object reference not set to an instance of an object.

Server stack trace:

at NHibernate.Engine.TypedValue..ctor(IType type, Object value, EntityMode entityMode) in C:\junctions\BS\3rdParty\NHibernate.2.1.2.GA-src\src\NHibernate\Engine\TypedValue.cs: line 25

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

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

at MyProject.Dao.MyClassDao.FilterByCategoryID(List`1 categoryIDs) in MyClassDao.cs: line 50

What would be the best way to solve this? Please note that the named query is of course far more complicated than the one presented above, so I'd like to avoid copying it to a second version that doesn't use the parameter list.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤云独去闲 2024-09-25 12:09:55

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

将您的查询修改为:

<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 语句有效。

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

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

但它确实能完成工作。

I have just faced the same issue, so I though I need to share the solution:

Modify your query to:

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

And the code to:

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

Explanation:

  1. We modify query to ignore categories when no such available.
  2. We modify an additional parameter to indicate (1).
  3. We add random ID that is never used. Just to make sure the IN SQL statement is valid.

So this way you can keep your complex query and just add additional parameters to it.

Obvious disadvantage is that it passes unnecessary parameter.

But it does the job.

笑看君怀她人 2024-09-25 12:09:55

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

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

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

I believe you can avoid that error by using .NET's Cast

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

That should return an empty list, not an exception.

一个人的夜不怕黑 2024-09-25 12:09:55

测试列表是否为空并执行其他操作。
在这个特定的查询中,您需要所有不在类别 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>();
}

test if the list is empty and do something else.
in this particular query you want all the MyClassBE that are not in the category ids which means all of them:

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>();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文