如何为存储过程添加try catch

时间:2017-03-04 20:53:45

标签: c# sql-server stored-procedures try-catch

我有一个存储过程'Class_set',当用户尝试将类添加到数据库时会触发该过程。存储过程检查数据库中是否存在任何冲突,如果不存在冲突,则将该类插入数据库。

目前,如果存在冲突,则会抛出51000错误,但我希望使用标签或面板在前端显示错误以显示相应的消息。我尝试使用try catch但是没有成功。

我的存储过程:

CREATE procedure dbo.Class_set ( 
   @moduledata int 
  , @startdatedata datetime 
  , @enddatedata datetime 
  , @classtypedata int 
  , @roomcodedata int 
  , @starttimedata int 
  , @endtimedata int 
  , @recurrencedata int 
  , @daydata int 
) as 
begin; 
  set nocount, xact_abort on; 
  /* temp table */ 
 select 
    DayId = @daydata 
  , ModuleId =@moduledata 
  , ClassTypeId = @classtypedata 
  , ClassScheduleStartTimeId = @starttimedata 
  , ClassScheduleEndTimeId = @endtimedata 
  , RoomCodeId = @roomcodedata 
  , StartTime= convert(datetime,c.Date) + s.StartTime 
  , EndTime = convert(datetime,c.Date) + e.EndTime 
  , RecurrenceId = @recurrencedata 
into #temp_class 
from Calendar c 
  cross apply ( 
    select StartTime = convert(datetime,ClassTime) 
    from ClassSchedule 
    where ClassScheduleId = @starttimedata 
    ) as s 
  cross apply ( 
   select EndTime = convert(datetime,ClassTime) 
   from ClassSchedule 
   where ClassScheduleId = @endtimedata 
   ) as e 
where c.Date >= @startdatedata 
  and c.Date <= @enddatedata 
  and c.isWeekDay = 1 
  and ( @recurrencedata != 2 
      or (@recurrencedata = 2 and c.DayOfWeek = @daydata) 
       ); 

/* check for conflicts */ 
if exists( 
  select 1 
  from dbo.[Class] c 
     inner join #temp_class t 
       on c.RoomCodeId = t.RoomCodeId 
      and t.EndTime > c.StartTime 
      and c.EndTime > t.StartTime 
  ) 
begin; 
    throw 51000, 'Room conflict exists',1; 
    return -1; 
    end; 

/* insert */ 
insert into dbo.[Class] (DayId, ModuleId, ClassTypeId 
    , ClassScheduleStartTimeId, ClassScheduleEndTimeId 
    , RoomCodeId, StartTime, EndTime, RecurrenceId ) 
select DayId, ModuleId, ClassTypeId 
   , ClassScheduleStartTimeId, ClassScheduleEndTimeId 
   , RoomCodeId, StartTime, EndTime, RecurrenceId 
from #temp_class 

end;
go

调用存储过程的方法:

  internal void insert_days( int daydata, int moduledata, int? recurrencedata, DateTime startdatedata, DateTime enddatedata, int classtypedata, int roomcodedata, int starttimedata, int endtimedata, string totalday)
    {

        {

            string connectionString = WebConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;

            using (SqlConnection myConnection = new SqlConnection(connectionString))
            {
                using (SqlCommand cmd = new SqlCommand("Class_set", myConnection))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue("@daydata", daydata);
                    cmd.Parameters.AddWithValue("@moduledata", moduledata);
                    cmd.Parameters.AddWithValue("@classtypedata", classtypedata);
                    cmd.Parameters.AddWithValue("@startdatedata", startdatedata);
                    cmd.Parameters.AddWithValue("@enddatedata", enddatedata);
                    cmd.Parameters.AddWithValue("@roomcodedata", roomcodedata);
                    cmd.Parameters.AddWithValue("@starttimedata", starttimedata);
                    cmd.Parameters.AddWithValue("@endtimedata", endtimedata);
                    cmd.Parameters.AddWithValue("@recurrencedata", recurrencedata);

                    myConnection.Open();
                    cmd.ExecuteNonQuery();
                }
            }


        }
    }

我尝试捕获:

  internal void insert_days(int daydata, int moduledata, int? recurrencedata, DateTime startdatedata, DateTime enddatedata, int classtypedata, int roomcodedata, int starttimedata, int endtimedata, string totalday) 
{ 
  { 
    try 
    { 
       string connectionString = WebConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString; 

      SqlConnection myConnection = new SqlConnection(connectionString); 

     using (SqlCommand cmd = new SqlCommand("Class_set", myConnection)) 
        { 
        cmd.CommandType = CommandType.StoredProcedure; 
        cmd.Parameters.AddWithValue("@daydata", daydata); 
        cmd.Parameters.AddWithValue("@moduledata", moduledata); 
        cmd.Parameters.AddWithValue("@classtypedata", classtypedata); 
        cmd.Parameters.AddWithValue("@startdatedata", startdatedata); 
        cmd.Parameters.AddWithValue("@enddatedata", enddatedata); 
        cmd.Parameters.AddWithValue("@roomcodedata", roomcodedata); 
        cmd.Parameters.AddWithValue("@starttimedata", starttimedata); 
        cmd.Parameters.AddWithValue("@endtimedata", endtimedata); 
        cmd.Parameters.AddWithValue("@recurrencedata", recurrencedata); 

        myConnection.Open(); 
        cmd.ExecuteNonQuery(); 
    } 
} 
 catch (SqlException ex) 
  { 
      switch (ex.Number) 
       { 
         case 51000: 
         Console.WriteLine("Error: Clashes exist with your current Room selection"); 
         break; 

         default:
         Console.WriteLine("Success: No clashes exist with your current Room selection");            

      } 
   } 
 }  
}  

抛出当前错误的图像: enter image description here

2 个答案:

答案 0 :(得分:2)

将SQL包装在try catch中。

CREATE PROCEDURE dbo.Class_set ( 
   @moduledata int 
  , @startdatedata datetime 
  , @enddatedata datetime 
  , @classtypedata int 
  , @roomcodedata int 
  , @starttimedata int 
  , @endtimedata int 
  , @recurrencedata int 
  , @daydata int 
) AS 
BEGIN 
    set nocount, xact_abort on; 
    /* temp table */ 

    BEGIN TRY
        select 
            DayId = @daydata 
          , ModuleId =@moduledata 
          , ClassTypeId = @classtypedata 
          , ClassScheduleStartTimeId = @starttimedata 
          , ClassScheduleEndTimeId = @endtimedata 
          , RoomCodeId = @roomcodedata 
          , StartTime= convert(datetime,c.Date) + s.StartTime 
          , EndTime = convert(datetime,c.Date) + e.EndTime 
          , RecurrenceId = @recurrencedata 
        into 
            #temp_class 
        from 
            Calendar c 
            cross apply ( 
            select StartTime = convert(datetime,ClassTime) 
            from ClassSchedule 
            where ClassScheduleId = @starttimedata 
            ) as s 
            cross apply ( 
            select EndTime = convert(datetime,ClassTime) 
            from ClassSchedule 
            where ClassScheduleId = @endtimedata 
            ) as e 
        where 
            c.Date >= @startdatedata 
            and c.Date <= @enddatedata 
            and c.isWeekDay = 1 
            and ( @recurrencedata != 2 
                or (@recurrencedata = 2 and c.DayOfWeek = @daydata) 
            ); 

            /* insert */ 
            insert into dbo.[Class] (DayId, ModuleId, ClassTypeId 
                , ClassScheduleStartTimeId, ClassScheduleEndTimeId 
                , RoomCodeId, StartTime, EndTime, RecurrenceId ) 
            select DayId, ModuleId, ClassTypeId 
               , ClassScheduleStartTimeId, ClassScheduleEndTimeId 
               , RoomCodeId, StartTime, EndTime, RecurrenceId 
            from #temp_class 
    END TRY
    BEGIN CATCH
        THROW
    END CATCH;
END
GO

添加标量函数以进行验证:

CREATE FUNCTION dbo.RoomConflict
(
    @RoomCode INT,
    @StartTime TIME(7),
    @EndTime TIME(7)
)
RETURNS INT
AS
BEGIN
    RETURN (
        SELECT 
            COUNT(*) 
        FROM 
            dbo.Class A 
        WHERE 
            A.RoomCodeId = @RoomCode AND @EndTime > A.StartTime AND A.EndTime > @StartTime)
END
GO

然后在dbo.Class表中添加一个约束:

ALTER TABLE [dbo].[Class] WITH NOCHECK ADD CONSTRAINT [CK_NoRoomConflict] CHECK (
    [dbo].[RoomConflict]([RoomCodeId],[StartTime],[EndTime]) = 0
)
GO
ALTER TABLE [dbo].[Class] CHECK CONSTRAINT [CK_NoRoomConflict]
GO

答案 1 :(得分:0)

我能够编辑Web.Config文件以添加customErrors,将用户重定向到我已解释问题的网站上的新页面。它并不理想,因为我希望在他们当前所在的页面上显示某些内容,但这是我目前唯一能找到的解决方案。

   <configuration>
      <system.web>
             <customErrors mode="On" defaultRedirect="ErrorPage.aspx?handler=customErrors%20section%20-%20Web.config">
              <error statusCode="510" redirect="ErrorPage.aspx?msg=404&amp;handler=customErrors%20section%20-%20Web.config"/>
              </customErrors>
       </system.web>
  </configuration>