NHibernate GetNamedQuery执行存储过程但返回空列表

时间:2014-01-09 21:28:52

标签: nhibernate stored-procedures sql-server-2012

我有一个存储过程,在使用此脚本在SQL Studio Management Express中测试时返回2条记录:

declare @route_id_param as varchar(10), @start_time as datetime, @start_date as datetime, @end_date as datetime
set @start_time = GETDATE()
set @start_date = CONVERT(DATETIME,'10/26/2013',101) 
set @end_date = CONVERT(DATETIME,'12/26/2020',101)     

exec dbo.sp_get_deactivation_list @companyId=1, @startDate = @start_date, @endDate = @end_date;
select execution_time_in_ms = DATEDIFF(millisecond, @start_time, getdate())
GO

当我尝试从NHibernate执行相同的存储过程时,使用以下映射文件,我得到0结果。

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping 
  xmlns="urn:nhibernate-mapping-2.2" 
  assembly="HGT.IridiumAirtime.Service" 
  namespace="HGT.IridiumAirtime.Service.Model">
  <sql-query name="GetDeactivationList" callable="true">
    <query-param name="companyId" type="int"/>
    <query-param name="startDate" type="DateTime"/>
    <query-param name="endDate" type="DateTime"/>
    <!--<return class="Activation">
      <return-property column="MobileId" name="MobileId" />
      <return-property column="RadioAddress" name="RadioAddress" />
      <return-property column="DeactivationDate" name="DeactivationDate" />
    </return>-->
    exec [sp_get_deactivation_list] @companyId=:companyId, @startDate=:startDate, @endDate=:endDate
  </sql-query>

</hibernate-mapping>

执行所述存储过程的方法是:

   public IEnumerable<TOut> ExecuteStoredProcedure<TOut>(string procedureName, IList<SqlParameter> parameters)
    {
        IEnumerable<TOut> result;

        using (var session = _sessionFactory.OpenSession())
        {
            var query = session.GetNamedQuery(procedureName);
            foreach (var parameter in parameters)
            {
                query.SetParameter(parameter.ParameterName, parameter.Value);
            }
            AddStoredProcedureParameters(query, parameters);
            result = query.List<TOut>(); 
        }

        return result;
    }

我甚至为这种激活类型创建了一个新的映射文件,即使没有关联的表但是NHibernate没有返回正确的结果。在过程的映射文件中取消注释类型映射定义不会更改结果。我在这里错过了什么吗?

我没有例外,因此看起来正在执行过程。

更新:1 删除了对 AddStoredProcedureParameters 的调用,并替换为方法正文。

更新2 添加存储过程:

if OBJECT_ID ( 'dbo.[sp_get_deactivation_list]', 'P' ) is not null 
    drop procedure dbo.[sp_get_deactivation_list];
go

create procedure [dbo].[sp_get_deactivation_list]   
    @companyId int,
    @startDate DateTime,
    @endDate DateTime
as
begin       
    select 
        assMobileRadio.Mobile_ID as MobileId, 
        tblRadioinfo.Radio_Address as RadioAddress, 
        tblRadioinfo.Deactivation_Date as DeactivationDate
    from tblRadioinfo 
    left join assMobileRadio 
    on tblRadioinfo.Radio_ID = assMobileRadio.Radio_ID
    where tblRadioinfo.Radio_Type_ID in (2, 4, 7) 
    and tblRadioinfo.Company_ID = @companyId
    and tblRadioinfo.Deactivation_Date <= @endDate
    and tblRadioinfo.Deactivation_Date >= @startDate
    and tblRadioinfo.Radio_Address in (select IMEI from [airtime_cdrs] where  Effective_Date > @startDate and Effective_Date < @endDate)
from airtimes_cte for xml path('')),1,1,''))    
    ORDER BY tblRadioinfo.Deactivation_Date
end

3 个答案:

答案 0 :(得分:3)

我刚刚尝试了你的映射(尽可能相同)和你的1)映射和2)调用是可以的。除了我不确定 AddStoredProcedureParameters

内部的电话这一事实

所以,这是有效的:

var query = session.GetNamedQuery("GetDeactivationList");
    query.SetParameter("companyId", 1);
    query.SetParameter("startDate", new DateTime(2013,10,26));
    query.SetParameter("endDate", new DateTime(2020,12,26));

// if the <return class="Activation"> is commented ... we'll get object[]
var list = query.List<object[]>(); 

这是有效的。也就是说。你的映射工作正常。 SQL调用(exec sp)被触发,因为如果找不到命名查询,或者会发生其他一些问题,我们将获得Exception

现在唯一可疑的是黑匣子 AddStoredProcedureParameters (无法切换开始和结束日期?)

我建议,在SQL Server Profiler中检查你的单元测试,你会看到传递给DB的内容......你可以接受并重新执行。

答案 1 :(得分:2)

如果您执行存储过程是您的主要目的(不完全使用GetNamedQuery),您可以使用以下内容:

假设你的方法的参数是:int? id,DateTime? fromDate,DateTime? toDate(所有可以为空的值)

IList<TOut> result = session.CreateSQLQuery("exec [dbo].[sp_get_deactivation_list]:param1, :param2, :param3")
    .SetParameter("param1", id, NHibernateUtil.Int32)
    .SetParameter("param2", fromDate, NHibernateUtil.DateTime)
    .SetParameter("param3", toDate, NHibernateUtil.DateTime)
    .SetResultTransformer(Transformers.AliasToBean<TOut>()).List<TOut>();

return result;

在类TOut的映射文件中,只需正常使用相关属性。

答案 2 :(得分:0)

如果Activation是带有nhibernate的非托管实体,您可以使用:

var query = session.GetNamedQuery(procedureName);

AddStoredProcedureParameters(query, parameters);

result = query.SetResultTransformer(Transformers.AliasToBean(typeof(TOut)))
    .List<TOut>();

如果尝试添加alias

<return alias="activation" class="Activation">
     ...
</return>

例如:

<sql-query name="mySqlQuery">
    <return alias="person" class="eg.Person">
        <return-property name="Name" column="myName"/>
        <return-property name="Age" column="myAge"/>
        <return-property name="Sex" column="mySex"/>
    </return>
    SELECT person.NAME AS myName,
           person.AGE AS myAge,
           person.SEX AS mySex,
    FROM PERSON person WHERE person.NAME LIKE :name
</sql-query>

参考here是解决问题的更多方法。 只是你需要怎么说nhibernate如何返回数据,“这个”列“解析这个”属性。

抱歉我的英语很差。