如何在名为IQuery参数的NHibernate上设置C#可空值类型值?

Dan*_*haw 31 nhibernate parameters null

我正在使用NHibernate并通过命名查询调用存储过程:

<sql-query name="SearchStuff" read-only="true" cacheable="true">
  <return class="ResultEntity" />
  EXEC [SearchStuff] ?, ?, ?    </sql-query>
Run Code Online (Sandbox Code Playgroud)

许多存储过程参数都是故意可以为空的 - 这是无法更改的.

C#:

IQuery listQuery = this.Session.GetNamedQuery("SearchStuff");
listQuery.SetInt32(0, param1);
listQuery.SetDateTime(1, param2);
listQuery.SetString(2, param3);
IList<ResultEntity> results = listQuery.List<ResultEntity>();
Run Code Online (Sandbox Code Playgroud)

不幸的是,NHibernate没有为可为空的值类型提供任何SetXyz()方法,所以我尝试添加一些扩展方法来补偿:

public static class QueryExtensions
{
    public static void SetInt32(this IQuery query, int position, int? val)
    {
        if (val.HasValue)
        {
            query.SetInt32(position, val.Value);
        }
        else
        {
            query.SetParameter(position, null);
        }
    }

    public static void SetInt32(this IQuery query, string name, int? val)
    {
        if (val.HasValue)
        {
            query.SetInt32(name, val.Value);
        }
        else
        {
            query.SetParameter(name, null);
        }
    }

    public static void SetDateTime(this IQuery query, int position, DateTime? val)
    {
        if (val.HasValue)
        {
            query.SetDateTime(position, val.Value);
        }
        else
        {
            query.SetParameter(position, null);
        }
    }

    public static void SetDateTime(this IQuery query, string name, DateTime? val)
    {
        if (val.HasValue)
        {
            query.SetDateTime(name, val.Value);
        }
        else
        {
            query.SetParameter(name, null);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试了各种版本,但都没有用.上面的代码失败并出现错误:

System.ArgumentNullException : A type specific Set(position, val) should be called because the Type can not be guessed from a null value.
Run Code Online (Sandbox Code Playgroud)

我也尝试过不设置参数,但NHibernate需要设置每个参数.我尝试使用位置和命名版本具有相同的结果.

有没有办法在NHibernate命名查询中为值类型参数赋值空值?

Dan*_*haw 52

好的,事实证明在SetParameter上有一些覆盖允许明确设置类型.例如:

query.SetParameter(position, null, NHibernateUtil.Int32);
Run Code Online (Sandbox Code Playgroud)

完整的扩展方法(仅限Int32和DateTime)现在是:

public static class QueryExtensions
{
    public static void SetInt32(this IQuery query, int position, int? val)
    {
        if (val.HasValue)
        {
            query.SetInt32(position, val.Value);
        }
        else
        {
            query.SetParameter(position, null, NHibernateUtil.Int32);
        }
    }

    public static void SetInt32(this IQuery query, string name, int? val)
    {
        if (val.HasValue)
        {
            query.SetInt32(name, val.Value);
        }
        else
        {
            query.SetParameter(name, null, NHibernateUtil.Int32);
        }
    }

    public static void SetDateTime(this IQuery query, int position, DateTime? val)
    {
        if (val.HasValue)
        {
            query.SetDateTime(position, val.Value);
        }
        else
        {
            query.SetParameter(position, null, NHibernateUtil.DateTime);
        }
    }

    public static void SetDateTime(this IQuery query, string name, DateTime? val)
    {
        if (val.HasValue)
        {
            query.SetDateTime(name, val.Value);
        }
        else
        {
            query.SetParameter(name, null, NHibernateUtil.DateTime);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果从方法中返回查询对象,则还可以获得正确的链接,例如:public static IQuery SetDateTime(... ... retrun query; (3认同)

Gui*_*rez 11

另一种方法是:

query.SetParameter<int?>(0, null);
query.SetParameter<DateTime?>(1, null);
...
Run Code Online (Sandbox Code Playgroud)

等等...

注意?使基元类型为空的符号.