【问题标题】:Stored procedure not working with .ASMX file存储过程不适用于 .ASMX 文件
【发布时间】:2013-06-24 11:24:36
【问题描述】:

任何人都知道为什么以下内容不起作用:

[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 server management studio 中通过单击存储过程名称并选择执行来执行它),我得到 0.666667(值将根据当前日期/时间和日期而有所不同/time 进入存储过程)。但是当我运行 .asmx 文件时,我得到 994728.666667。

有人知道为什么会这样吗?基本上,两个示例中的 .666667 部分都是正确的,但由于某种原因,.asmx 文件似乎将 994728 添加到了正确的值中。

【问题讨论】:

  • “手动运行存储过程”是什么意思?你的意思是在sql studio中执行?
  • 我相信您应该将DateTime 对象而不是strMeetingDate(类型为string)传递给存储过程。 strMeetingTime 也是如此。
  • @RosdiKasim,手动,就像我从 sql server management studio 中选择存储过程一样,然后单击执行。
  • 您是否检查过要发送到方法内存储过程的参数?我会怀疑你的参数是 GIGO。由于日期值以字符串形式出现,这始终是一种风险。最重要的是,您将日期值作为字符串处理,这也可能导致问题。
  • 正如前面的 cmets 中提到的,我也会怀疑从字符串值分配日期/时间参数。我会先根据需要解析或 TryParse 字符串,然后从生成的 C# DateTime 值中分配参数值。如果没有别的,它让您有机会在将转换结果移交给 SQL 之前检查并确认转换结果。

标签: c# sql-server-2005 .net-3.5 asmx asp.net-3.5


【解决方案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"];
            }
        }
    }
}

然后更改您的存储过程以从您的参数中解析出日期和时间:

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]

【讨论】:

    【解决方案2】:

    您可以启动SQL Server Profiler 并亲自查看传递给您的过程的参数。

    引用answer“SQL Server 如何决定隐式日期时间转换的格式?”

    “这可能取决于多种因素 - 操作系统的区域设置、当前用户的语言和日期格式设置。默认情况下,Windows 使用美国英语,而用户的设置是美国英语和 MDY。”

    “您最好的选择始终是使用 ISO 标准、非区域、安全、明确的日期格式,例如 YYYYMMDD 用于日期,YYYY-MM-DDTHH:MM:SS[.mmm] 用于日期+时间。”

    如果可能的话,我会在您的 Web 服务界面中将字符串更改为 DateTime 并检查 sql 跟踪以确保该调用与您从管理工作室手动执行的内容相对应。

    【讨论】:

      猜你喜欢
      • 2011-01-23
      • 2015-11-11
      • 1970-01-01
      • 2021-09-04
      • 2011-09-16
      • 1970-01-01
      • 2018-05-21
      • 2011-09-21
      • 2010-12-02
      相关资源
      最近更新 更多