2013-06-24 4 views
0

Любой знает, почему следующее не работает:Хранимая процедура не работает с .asmx файл

[WebMethod()] 
public double GetDayCount(string strMeetingDate, string strMeetingTime) 
{ 
    string[] strStartDateParts = strMeetingDate.Split('-'); 

    // change DMY to YMD 
    strMeetingDate = strStartDateParts[2] + '-' + strStartDateParts[1] + '-' + strStartDateParts[0]; 

    using (connection = new SqlConnection(ConfigurationManager.AppSettings["connString"])) 
    { 

     using (command = new SqlCommand("BusinessHours", connection)) 
     { 

      command.CommandType = CommandType.StoredProcedure; 
      command.Parameters.Add("@meeting_day", SqlDbType.DateTime).Value = strMeetingDate; 
      command.Parameters.Add("@meeting_time", SqlDbType.DateTime).Value = strMeetingTime; 

      connection.Open(); 

      using (reader = command.ExecuteReader()) 
      { 
       reader.Read(); 
       return (double)reader["hours"]; 
      } 
     } 
    } 
} 

Нет сообщений об ошибках возвращается, а возвращаемое значение неверно.


Здесь представлена ​​полная хранимая процедура.

USE [INTRANET] 
GO 
/****** Object: StoredProcedure [dbo].[BusinessHours] Script Date: 06/24/2013 11:38:40 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[BusinessHours] 

@meeting_day DATETIME, 
@meeting_time DATETIME 

AS 

DECLARE @submit_day DATETIME; 
DECLARE @submit_time DATETIME; 

DECLARE @start_time_of_business_day DATETIME; 
DECLARE @business_day_hours FLOAT; 

DECLARE @num1 FLOAT 
DECLARE @num2 FLOAT 
DECLARE @num3 FLOAT 

SET @submit_day = CONVERT(VARCHAR(10),GETDATE(),101); 
SET @submit_time = CONVERT(VARCHAR(8),GETDATE(),108); 

SET @start_time_of_business_day = '09:00'; 
SET @business_day_hours = 8.5; 

SET @num1 = ((DATEDIFF(dd, @submit_day, @meeting_day)) 
-(DATEDIFF(wk, @submit_day, @meeting_day) * 2) 
-(CASE WHEN DATEPART(dw, @submit_day) = 1 THEN 1 ELSE 0 END) 
-(CASE WHEN DATEPART(dw, @meeting_day) = 7 THEN 1 ELSE 0 END) 
-(SELECT COUNT(*) FROM bank_holiday WHERE the_date BETWEEN @submit_day AND @meeting_day)) * @business_day_hours 
SET @num2 = (select datediff(minute, @start_time_of_business_day, @submit_time))/60.0 
SET @num3 = (select datediff(minute, @start_time_of_business_day, @meeting_time))/60.0 

select @num1 - @num2 + @num3 as [hours] 

Если я запустить хранимую процедуру вручную (как при выполнении его изнутри SQL Studio для управления сервером, нажав на сохраненное имя процедуры и выбор выполнения), я получаю 0,666667 (значение будет отличаться в зависимости от текущей даты/время и дата/время, введенные в хранимую процедуру). Но когда я запускаю файл .asmx, я получаю 994728.666667.

Кто-нибудь знает, почему это происходит? В принципе, часть .666667 верна в обоих примерах, но почему-то файл .asmx добавляет 994728 к правильному значению.

+0

Что вы имеете в виду «запустить хранимую процедуру вручную»? Вы имеете в виду, что вы выполняете его в sql-студии? –

+0

Я считаю, что вы должны передать хранимую процедуру объект 'DateTime' вместо strMeetingDate (который имеет тип' string'). То же самое для strMeetingTime. –

+0

@RosdiKasim, вручную, как и при выборе хранимой процедуры из студии управления сервером sql и нажмите «выполнить». – oshirowanen

ответ

1

Вы передаете строку как параметр DateTime. Следующие должны работать:

[WebMethod()] 
public double GetDayCount(string strMeetingDate, string strMeetingTime) 
{ 
    string[] strStartDateParts = strMeetingDate.Split('-'); 
    // not sure what your expected time format is 
    string[] srtStartTimeParts = strMeetingTime.Split('-'); 

    int year = Int32.Parse(strStartDateParts[2]); 
    int month = Int32.Parse(strStartDateParts[1]); 
    int day = Int32.Parse(strStartDateParts[0]); 
    int hour = Int32.Parse(srtStartTimeParts[0]); 
    int min = Int32.Parse(srtStartTimeParts[1]); 
    int sec = Int32.Parse(srtStartTimeParts[2]); 

    DateTime meetingDate = new DateTime(year, month, day, hour, min, sec); 
    using (connection = new SqlConnection(ConfigurationManager.AppSettings["connString"])) 
    { 
     using (command = new SqlCommand("BusinessHours", connection)) 
     { 
      command.CommandType = CommandType.StoredProcedure; 
      command.Parameters.Add("@meeting_date", SqlDbType.DateTime).Value = meetingDate; 
      connection.Open(); 
      using (reader = command.ExecuteReader()) 
      { 
       reader.Read(); 
       return (double)reader["hours"]; 
      } 
     } 
    } 
} 

Затем измените sproc, чтобы разобрать дату и время с вашего аргумента:

ALTER PROCEDURE [dbo].[BusinessHours] 

@meeting_date DATETIME 

AS 

DECLARE @meeting_day DATETIME 
DECLARE @meeting_time DATETIME 
DECLARE @submit_day DATETIME; 
DECLARE @submit_time DATETIME; 

DECLARE @start_time_of_business_day DATETIME; 
DECLARE @business_day_hours FLOAT; 

DECLARE @num1 FLOAT 
DECLARE @num2 FLOAT 
DECLARE @num3 FLOAT 

SET @meeting_day = CONVERT(VARCHAR(10),@meeting_date,101); 
SET @meeting_time = CONVERT(VARCHAR(8),@meeting_date,108); 

SET @submit_day = CONVERT(VARCHAR(10),GETDATE(),101); 
SET @submit_time = CONVERT(VARCHAR(8),GETDATE(),108); 

SET @start_time_of_business_day = '09:00'; 
SET @business_day_hours = 8.5; 

SET @num1 = ((DATEDIFF(dd, @submit_day, @meeting_day)) 
-(DATEDIFF(wk, @submit_day, @meeting_day) * 2) 
-(CASE WHEN DATEPART(dw, @submit_day) = 1 THEN 1 ELSE 0 END) 
-(CASE WHEN DATEPART(dw, @meeting_day) = 7 THEN 1 ELSE 0 END) 
-(SELECT COUNT(*) FROM bank_holiday WHERE the_date BETWEEN @submit_day AND @meeting_day)) * @business_day_hours 
SET @num2 = (select datediff(minute, @start_time_of_business_day, @submit_time))/60.0 
SET @num3 = (select datediff(minute, @start_time_of_business_day, @meeting_time))/60.0 

select @num1 - @num2 + @num3 as [hours] 
0

Вы можете начать SQL Server Profiler и сами убедиться, какие параметры переданы вашей процедуре.

Процитировать answer на тему «Как SQL Server определяет формат для неявного преобразования даты и времени?»

«Это может зависеть от множества факторов - от региональных настроек операционной системы, от языка текущего пользователя и от формата даты. По умолчанию Windows использует US English, а пользовательские настройки - английский и английский.

«Ваш лучший выбор - всегда использовать стандартные, нерегиональные, безопасные и однозначные форматы даты, такие как YYYYMMDD для дат и YYYY-MM-DDTHH: MM: SS [.mmm] для даты + времени».

Я бы, если возможно, изменил строку на DateTime в вашем веб-сервисном интерфейсе и проверил sql-трассировку, чтобы убедиться, что вызов соответствует тому, что вы выполняете вручную из студии управления.