在某些情况下调用SQL Server存储过程失败

时间:2015-10-27 22:48:27

标签: c# sql-server database stored-procedures

我正在努力理解为什么某个存储过程已停止在我的一些数据库中工作,而在其他数据库中却没有。我希望有人可以帮我解决这个问题。

简介

我继承了一个现有的C#应用​​程序,该应用程序根据提供给程序的culture参数连接到一系列SQL Server数据库。示例:传递“ en-CA ”会导致程序使用英语 - 加拿大内容连接到数据库。传递“ fr-CA ”会导致程序使用法语 - 加拿大内容连接到数据库。数据库源自公共根数据库。除了许多 NVARCHAR 字段的内容之外,数据库基本相同。 (这种数据库仅在开发过程中用于测试各种文化。

两个数据库都使用以下排序规则: SQL_Latin1_General_CP1_CI_AS

问题

我不确定此问题何时开始,但目前的情况是,如果我从 fr-CA 数据库调用某个存储过程,则根本不会执行。 (我将更详细地解释这一点。)没有错误代码返回给程序。该程序就好像没有找到记录一样。

但是,如果我从 en-CA 数据库调用相同的存储过程,那么它将按预期运行,并将记录返回给程序。

尝试的步骤

如果我从SSMS运行存储过程,那么它会正确执行。

Successful execution of stored procedure.

我尝试将存储过程的定义从正确执行的数据库复制到未正确执行的数据库。这并没有解决问题。

我尝试使用SQL事件探查器进行调试。当我对两个数据库运行存储过程时,我在跟踪中看到一个条目。我没有看到列出任何错误。我承认在使用Profiler时我是新手。

当我说存储过程没有被执行时,我将基于以下测试。我创建了一个包含几个字段的调试表:

create table DEBUG
(
    Id INTEGER,
    Line NVARCHAR(100)
);

在存储过程的顶部,在两个数据库中,我插入了以下语句的第一行:

INSERT INTO dbo.DEBUG VALUES (1, 'Top of Atms_Get_Tray_Infos');

当我的代码调用存储过程时,我希望在 DEBUG 表中看到一行。

如果我针对 en-CA 数据库运行该程序,我确实看到了预期的行:

Expected debug line.

如果我清空 DEBUG 表,然后针对 fr-CA 数据库运行程序, DEBUG 表将保持为空。这一事实让我相信存储过程没有被执行。

数据库详细信息

以下是使用调试行的存储过程的定义:

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[Atms_Get_Tray_Infos]
    @TrayNo AS NVARCHAR(10)
AS
BEGIN
    -- DEBUG
    INSERT INTO dbo.DEBUG VALUES (1, 'Top of Atms_Get_Tray_Infos');

    -- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
    SET NOCOUNT ON;

    BEGIN TRY
        SELECT  HTRAY.SEQ_HIST_PLATEAU AS TRAYNO,
                HTRAY.DATE_EXPIRATION_DATE AS EXPIRY,
                HTRAY.DATE_UTILISATION_DATE AS DATEUSED,
                HTRAY.LADATE_LAVAGE AS WASHDATE,
                HSTE.SEQ_CODE_QUAL_STERIL AS QLTYCODE,
                HSTE.NO_CHARGE AS CHGNO,
                HSTE.TEST_BIO_BON AS BIOTEST,
                FRML.CODE AS FORMULACODE,
                TRAY.NO_TYPE_PLATEAU AS TRAYCODE,
                TRAY.DESCRIPTION_S,
                TRAY.EstUrgent AS URGENT
        FROM dbo.HIST_PLAT HTRAY
        LEFT JOIN dbo.HIST_CHARG_STE HSTE ON HTRAY.LAST_SEQ_HIST_CHARGE_STERIL = HSTE.SEQ_HIST_CHARGE_STERIL
        INNER JOIN dbo.PLATEAUX TRAY ON TRAY.SEQ_PLATEAU = HTRAY.NO_SEQ_PLATEAU
        INNER JOIN dbo.FORMULE FRML ON HSTE.SEQ_FORMULE = FRML.SEQ_FORMULE
        WHERE HTRAY.SEQ_HIST_PLATEAU = @TrayNo
    END TRY

    BEGIN CATCH
        DECLARE @ErrorMessage NVARCHAR(4000);
        DECLARE @ErrorSeverity INT;
        DECLARE @ErrorState INT;

        SELECT  @ErrorMessage = ERROR_MESSAGE(),
                @ErrorSeverity = ERROR_SEVERITY(),
                @ErrorState = ERROR_STATE();
        RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
    END CATCH
END

我感谢能够帮助我解决这个问题的任何帮助。谢谢!

1 个答案:

答案 0 :(得分:0)

上面Paolo的评论让我调查了调用存储过程的实际C#代码。

在我看来,为了让人感到困惑,代码很复杂。 有一种方法是处理对存储过程的所有调用的一些类。我用这个基本代码替换了代码:

DataSet dataSet = new DataSet("ReturnDs");
using (var connection = new System.Data.SqlClient.SqlConnection(theConnectStg))
{
    using (var command = new System.Data.SqlClient.SqlCommand(theStoreProcName, connection))
    {
        using (var dataAdapter = new System.Data.SqlClient.SqlDataAdapter(command))
        {
            command.CommandType = CommandType.StoredProcedure;
            if (theParameterList != null)
            {
                foreach (String str1 in theParameterList.ToArray())
                {
                    String parameterName = str1.Substring(0, str1.IndexOf(":"));
                    String str2 = str1.Substring(str1.IndexOf(":") + 1);
                    dataAdapter.SelectCommand.Parameters.Add(new SqlParameter(parameterName, SqlDbType.VarChar, 128));
                    dataAdapter.SelectCommand.Parameters[parameterName].Value = (object)str2;
                }
            }
            dataAdapter.Fill(dataSet);
        }
    }
}
return dataSet;

为了满足您的好奇心, theParameterList 参数是一个参数数组,每个参数的形式为“ @variable:value ”。我不是粉丝,但我现在仍然坚持现有的代码。

那么,为什么以前的代码对某些数据库失败了呢?我还是不知道。我很好奇,但我不想再花这么多时间在这个问题上。我的大脑累了。

谢谢你的线索,Paolo!