【问题标题】:ExecuteScalar "Specified cast is not valid" exceptionExecuteScalar“指定的强制转换无效”异常
【发布时间】:2014-02-16 04:31:03
【问题描述】:

以下代码行有时会导致“Specified cast is not valid”异常:

public static object Select(string sql, OleDbTransaction dbt)
{
  try
  {
     OleDbCommand cmd = new OleDbCommand(sql, lib.dbc, dbt);
     object obj = cmd.ExecuteScalar(); /* <- this is what fails */
     return obj;
  }
  catch (Exception ex)
  {
    /* deleted code - error message to the user */
    return null;
  }
}

这个函数在程序中执行了好几次才失败。如果在新的执行线程中执行 olny 时失败,则只有 有时。当我调用在线程中执行处理的程序部分并调用此函数时,它要么一直工作(=>我单击按钮,它执行,没有错误,我一次又一次地单击并执行.. .),或者它永远不会起作用(=> 我单击按钮并执行,异常,我再次单击并执行,再次异常...)。

lib.dbc -> OleDbConnection 类型的静态变量仅在程序启动时初始化,并且在整个代码中经常使用,有效

我不知道如何进一步调试它,最重要的是,对 object 类型的变量的哪些赋值可能会失败? ExecuteScalar 应该返回对象或 null。我使用的数据库是 Jet (MS Access)。

在异常中我找到了这个堆栈跟踪,也许它可以提供帮助:

at System.Data.OleDb.OleDbConnection.IOpenRowset()
at System.Data.OleDb.OleDbCommand.ExecuteTableDirect(CommandBehavior behavior, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
at System.Data.OleDb.OleDbCommand.ExecuteScalar()
at FK.sql.Select(String sql, OleDbTransaction dbt)

【问题讨论】:

  • 这里的 SQL 是什么?您是否实际上发出查询会产生单个值?
  • 您是否在多个线程上共享同一个连接? ADO.NET 不是为此而设计的。 @JonSkeet ExecuteScalar 返回“结果集中第一行的第一列,如果结果集为空,则返回空引用。”
  • @C.Evenhuis:好点。线程问题很可能是问题所在。将 ExecuteScalar 用于具有多个列/行 IMO 的结果仍然不是一个好主意,但它不应该给出这个错误。
  • SQL 总是“选择...”。它返回的内容应该不重要,它可能只会导致逻辑错误,因为该函数是用于管理任何 SELECT 结果的包装器。关于线程,我有一个主线程,对于这种特殊情况(长时间执行),它会产生 2 个其他线程——1 个 SQL 处理线程和 1 个对话线程。我发现了一些我的线程可能需要 ApartmentState = ApartmentState.MTA 的信息,我不太了解这是什么。在任何给定时刻,只有 1 个线程执行 SQL 操作。我的函数返回一个数据或 null,这就是它的工作。

标签: c# exception executescalar


【解决方案1】:

如果在新的执行线程中执行 olny 时会失败,然后只是有时。

此语句与您将连接作为参数传递的事实相结合,表明您可能正在尝试在多个线程上使用相同的数据库连接,也可能是事务。

不要:而是在每次要访问数据库时创建一个新连接:连接池意味着这将是高效的。

【讨论】:

  • 是的,我正在共享数据库连接,不知道在多线程环境中会造成如此严重的破坏。当我不在线程之间共享连接时,我无法重现错误。谢谢!
【解决方案2】:

试试这个,就像一个诊断工具:

public static object Select(string sql, OleDbTransaction dbt)
{
  try
  {
     using (OleDbConnection con = new OleDbConnection(lib.dbc.ConnectionString))
     using (OleDbCommand cmd = new OleDbCommand(sql, con, dbt))
     {
         object obj = cmd.ExecuteScalar();
         return obj;
     }
  }
  catch (Exception ex)
  {
    /* deleted code - error message to the user */
    return null;
  }
}

这可能有助于确定您是否有线程问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 2019-03-27
    • 2012-09-21
    • 1970-01-01
    相关资源
    最近更新 更多