【发布时间】: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