2014-01-09 3 views
2

У меня есть хранимая процедура, которая возвращает 2 записи при тестировании в SQL Studio Management Express, используя этот скрипт:NHibernate GetNamedQuery выполняет хранимую процедуру, но возвращает пустой список

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 и заменен методом тела.

UPDATE 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

Я только что пробовал ваше сопоставление (то же самое) и ваше 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 ... и вы можете принимать и повторно выполнять.

+0

+1 для ссылки на SQL Profiler. Поскольку я нахожусь в Express, я использовал ExpressProfiler с https://expressprofiler.codeplex.com/, который подтверждает выполнение следующего: exec sp_executesql N'exec [sp_get_deactivation_list] @ companyId = @ p0, @ startDate = @ p1, @ endDate = @ p2 ', N' @ p0 int, @ p1 datetime, @ p2 datetime ', @ p0 = 1, @ p1 =' 2013-10-26 00:00:00 ', @ p2 =' 2020-12 -16 00:00:00 ' переезд. Еще нет выхода. Почему вы делаете query.List вместо query.List ? –

+0

У меня есть аналогичная хранимая процедура, называемая GetTransmissionSum, успешно выполняемая через NHibernate. Когда этот выполняется, Express Profiler дает процессор 31, чтение 3788 и продолжительность 41 мс. Однако, когда GetDeactivationList выполняется, CPU равен 0, Reads равно 3, а длительность - 0ms. Когда я запускаю тестовый скрипт с GetDeactivationList в Studio Management Express, CPU составляет 125, читает 3991 и длительность 124 мс. –

+0

Когда я перепробовал запрос, передаваемый в БД, он возвращает значение 0. Хммм. –

0

Если активация не является управляемый объект с 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 - еще несколько способов решения вашей проблемы. Просто вам нужно сказать, чтобы запретить возврат данных, «этот» столбец «Разрешить это».

Извините за мой плохой английский.

+0

Спасибо, что ответили. query.SetResultTransformer(). Список () - это код, который у меня был перед запуском в связанную запись. Попробуй еще раз, но я помню, что это не сработало. Не могли бы вы прояснить второй абзац? Должен ли я раскомментировать сопоставление активации и добавить псевдоним? –

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, просто соответствующие свойства, как обычно.

+0

Спасибо, но были и другие проблемы, которые не были связаны с вызовом GetNamedQuery и его параметрами. –

Смежные вопросы