【问题标题】:try/catch block not catching an exceptiontry/catch 块没有捕获异常
【发布时间】:2014-07-27 17:55:15
【问题描述】:

我遇到了一个问题,即 try/catch 块没有捕获到异常。该问题发生在 command.ExecuteReader(),但它永远不会被捕获。我正在调试模式下运行,并且已经尝试了一些关于调试器设置的建议选项,但均无济于事。

我想提一下,我使用 SQLite 作为我的提供程序,我可以看到它抛出了 SQLiteException,但是问题仍然存在。是否存在未捕获异常的任何特定情况? (除了 StackOverflowException、ThreadAbortedException 等...)

    public IEnumerable<dynamic> Query(string sql, params object[] parms)
    {
        try
        {
            return QueryCore(sql, parms);
        }
        catch (Exception ex)
        {
            throw new DbException(sql, parms, ex);
        }
    }

    private IEnumerable<dynamic> QueryCore(string sql, params object[] parms)
    {
        using (var connection = CreateConnection())
        {
            using (var command = CreateCommand(sql, connection, parms))
            {
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        yield return reader.ToExpando();
                    }
                }
            }
        }
    }

我还想补充一点,如果我对数据库生成正确的查询,我会返回结果,但是当我中断查询时,会抛出异常,但不会被捕获。

【问题讨论】:

  • 当你从 catch 子句中删除参数时会发生什么?
  • 在 64 位机器上的 Form.Load 事件期间。

标签: c# sqlite exception-handling


【解决方案1】:

发生这种情况是因为您使用 yield 关键字返回数据。 这使得 data 实际数据方法仅在其结果被枚举时运行。

您可能不希望这种情况发生,尤其是因为如果将结果枚举两次(例如两个单独的 foreach 循环),则数据将被读取两次。 您可以这样做以使枚举立即发生并捕获任何异常:

public IEnumerable<dynamic> Query(string sql, params object[] parms)
{
    try
    {
        return QueryCore(sql, parms).ToArray();
    }
    catch (Exception ex)
    {
        throw new DbException(sql, parms, ex);
    }
}

Yielding 适用于获取项目需要一些时间的情况,并且您不想在循环之前获取所有项目。因此,另一种可能的解决方案可能会更好地提高代码的可读性(我认为不需要屈服):

public IEnumerable<dynamic> Query(string sql, params object[] parms)
{
    try
    {
        return QueryCore(sql, parms);
    }
    catch (Exception ex)
    {
        throw new DbException(sql, parms, ex);
    }
}

private IEnumerable<dynamic> QueryCore(string sql, params object[] parms)
{
    using (var connection = CreateConnection())
    {
        using (var command = CreateCommand(sql, connection, parms))
        {
            using (var reader = command.ExecuteReader())
            {
                var results = new List<dynamic>();
                while (reader.Read())
                {
                    results.Add(reader.ToExpando());
                }

                return results;
            }
        }
    }
}

【讨论】:

  • @Sash 很高兴听到这个消息。查看我的编辑,它可能会为您提供更多信息。
  • 太棒了——我会把它带到船上。我实际上对另一个数据库函数进行了确切的更改 - 但我认为我不会为 IEnumerable<...> 更健壮一点而烦恼。
  • @Sash 我仍然建议您应该返回一个 IEnumerable 而不是 IList,它更健壮。只是让步是不必要的。
  • 确实做到了 :) 非常好 - 工作就像一个魅力。它让我头脑清醒。浪费了 3 个小时,直到我最终屈服并来到这里,不到 5 分钟就得到了答案:)
猜你喜欢
  • 2019-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-26
  • 2019-11-11
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
相关资源
最近更新 更多