【问题标题】:Ado.net Fill method not throwing error on running a Stored Procedure that does not existAdo.net Fill 方法在运行不存在的存储过程时不会引发错误
【发布时间】:2010-04-09 17:17:14
【问题描述】:

我正在使用 Enterprise 库和 ADO 的原始 Fill 方法的组合。这是因为我在捕获事件信息消息时需要自己打开和关闭命令连接

这是我目前的代码

        // Set Up Command 
        SqlDatabase db = new SqlDatabase(ConfigurationManager.ConnectionStrings[ConnectionName].ConnectionString);
        SqlCommand command = db.GetStoredProcCommand(StoredProcName) as SqlCommand;
        command.Connection = db.CreateConnection() as SqlConnection;

        // Set Up Events for Logging
        command.StatementCompleted += new StatementCompletedEventHandler(command_StatementCompleted);
        command.Connection.FireInfoMessageEventOnUserErrors = true;
        command.Connection.InfoMessage += new SqlInfoMessageEventHandler(Connection_InfoMessage);

        // Add Parameters
        foreach (Parameter parameter in Parameters)
        {
            db.AddInParameter(command, 
                parameter.Name, 
                (System.Data.DbType)Enum.Parse(typeof(System.Data.DbType), parameter.Type), 
                parameter.Value);
        }

            // Use the Old Style fill to keep the connection Open througout the population
            // and manage the Statement Complete and InfoMessage events
            SqlDataAdapter da = new SqlDataAdapter(command);
            DataSet ds = new DataSet();

            // Open Connection
            command.Connection.Open();

            // Populate
            da.Fill(ds);

            // Dispose of the adapter
            if (da != null)
            {
                da.Dispose();
            }

            // If you do not explicitly close the connection here, it will leak!  
            if (command.Connection.State == ConnectionState.Open)
            {
                command.Connection.Close();
            }

...

现在如果我传入变量 StoredProcName = "ThisProcDoesNotExists"

然后运行这段代码。 CreateCommand 也没有 da.Fill 通过错误消息。为什么是这样。我可以告诉它没有运行的唯一方法是它返回一个包含 0 个表的数据集。但是在调查错误时,该过程似乎并不存在。

编辑 经进一步调查 command.Connection.FireInfoMessageEventOnUserErrors = true; 导致错误被抑制到 InfoMessage 事件中

来自 BOL

当您将 FireInfoMessageEventOnUserErrors 设置为 true 时,以前被视为异常的错误现在将作为 InfoMessage 事件处理。所有事件立即触发并由事件处理程序处理。如果 FireInfoMessageEventOnUserErrors 设置为 false,则 InfoMessage 事件将在过程结束时处理。

我想要的是来自 Sql 的每个打印语句来创建一个新的日志记录。将此属性设置为 false 会将其组合为一个大字符串。因此,如果我将属性设置为 true,那么现在的问题是我能否从错误中识别打印消息

另一个编辑

所以现在我有了代码,以便将标志设置为 true 并检查方法中的错误号

    void Connection_InfoMessage(object sender, SqlInfoMessageEventArgs e)
    {
        // These are not really errors unless the Number >0
        // if Number = 0 that is a print message
        foreach (SqlError sql in e.Errors)
        {
            if (sql.Number == 0)
            {
                Logger.WriteInfo("Sql Message",sql.Message);
            }
            else
            {

                // Whatever this was it was an error 
                throw new DataException(String.Format("Message={0},Line={1},Number={2},State{3}", sql.Message, sql.LineNumber, sql.Number, sql.State));
            }
        }
    }

现在的问题是,当我抛出错误时,它不会冒泡到发出调用的语句,甚至是高于它的错误处理程序。它只是在那条线上爆炸

填充看起来像

            // Populate
            try
            {
                da.Fill(ds);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message, e);
            }

现在即使我看到调用代码和方法仍在调用堆栈中,这个异常似乎没有冒泡?

【问题讨论】:

    标签: c# .net sql ado.net


    【解决方案1】:

    我在这方面花了一些时间,得出的结论是 InfoMessageHandler 没有在执行命令对象的范围内引发。因此,您在事件中抛出的异常不会冒泡到命令对象的方法。它必须在不同的线程中执行。

    我假设您使用的是 Visual Studio 2008,因为我能够在该环境中准确重现您的问题。当我将代码迁移到仍使用框架 3.5 的 Visual Studio 2010 时,新的 IDE 会捕获自定义异常,但我无法找到一种简单的方法来捕获代码中的异常。 Visual Studio 2010 调试器更擅长调试多线程。

    如果你想从这个事件中捕获异常,你将不得不编写可以跟踪线程异常的代码。

    【讨论】:

    • 我遇到了类似的问题,一旦我停止使用填充方法,我就能解决我的问题。 link
    猜你喜欢
    • 2012-12-19
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多