Skip to main content
 首页 » 编程设计

nhibernate之如何在名为IQuery参数的NHibernate上设置C#可为空的值键入值

2024年09月07日13lyhabc

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

<sql-query name="SearchStuff" read-only="true" cacheable="true"> 
  <return class="ResultEntity" /> 
  EXEC [SearchStuff] ?, ?, ?    </sql-query> 

许多存储过程参数是有意为空的-不能更改。

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

不幸的是,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); 
        } 
    } 
} 

我尝试了这些的各种版本,但没有用。上面的代码因错误而失败:
System.ArgumentNullException : A type specific Set(position, val) should be called because the Type can not be guessed from a null value. 

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

在NHibernate命名查询中,有什么方法可以将空值分配给值类型的参数?

请您参考如下方法:

好的,事实证明,在SetParameter上有一些替代,可以显式设置类型。例如:

query.SetParameter(position, null, NHibernateUtil.Int32); 

完整的扩展方法(仅适用于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); 
        } 
    } 
}