cmd = new SQLiteCommand();
...
if (Convert.ToInt32(cmd.ExecuteScalar()) == 0)
goto doClose;
else
cmd.CommandText = sql;
reader = cmd.ExecuteReader(); // this is line 182, check the exception details below
更多: 我要去睡觉了。下面是代码源(我的GitHub的回购),如果有人可以看看它? git@github.com:tomxuetoy / WPF_startPrograms.git
以上是我的代码,它可以正常工作。在我的情况下,由于cmd.ExecuteScalar()
表不存在,SQLite
将返回null。
我尝试改变它,如下所示但失败了:
if (cmd.ExecuteScalar() == null)
所以我想知道为什么我不能直接压缩表达式(null
返回)和null
?
谢谢!
更多: 下面的尝试但结果相同:无法正常工作
if (cmd.ExecuteScalar() == DBNull.Value)
or
if (cmd.ExecuteScalar() is DBNull)
下面复制了详细的例外情况,但有一些中文字符......
System.Windows.Markup.XamlParseException occurred
HResult=-2146233087
Message=对类型“MultiStart.MainWindow”的构造函数执行符合指定的绑定约束的调用时引发了异常。
Source=PresentationFramework
LineNumber=0
LinePosition=0
StackTrace:
在 System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
InnerException: System.Data.SQLite.SQLiteException
HResult=-2147467259
Message=SQLite error
no such table: testTable
Source=System.Data.SQLite
ErrorCode=-2147467259
StackTrace:
在 System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn, String strSql, SQLiteStatement previous, UInt32 timeoutMS, String& strRemain)
在 System.Data.SQLite.SQLiteCommand.BuildNextCommand()
在 System.Data.SQLite.SQLiteCommand.GetStatement(Int32 index)
在 System.Data.SQLite.SQLiteDataReader.NextResult()
在 System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
在 System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
在 System.Data.SQLite.SQLiteCommand.ExecuteReader()
在 MultiStart.MainWindow.dbOp(dowhat dw) 位置 c:\Users\Administrator\Desktop\WPF_startPrograms\WpfApplication2\WpfApplication2\MainWindow.xaml.cs:行号 182
在 MultiStart.MainWindow.DataBinding() 位置 c:\Users\Administrator\Desktop\WPF_startPrograms\WpfApplication2\WpfApplication2\MainWindow.xaml.cs:行号 43
在 MultiStart.MainWindow..ctor() 位置 c:\Users\Administrator\Desktop\WPF_startPrograms\WpfApplication2\WpfApplication2\MainWindow.xaml.cs:行号 36
InnerException:
答案 0 :(得分:3)
更好的方法是检查表是否存在。其中一种方法是调用DbConnection.GetSchema(string)
传入SqLite用于其表模式的任何参数。
我没有要测试的SqLite数据库,但它会是这样的
var tableName = "testTable";
var commandText = "Select * from " + tableName;
using(var conn = new SQLiteConnection(connectionString))
{
conn.Open();
var schema = conn.GetSchema("Tables", new string[] { null, null, tableName });
if(schema.Rows.Count == 0) //I am assuming your original ExecuteScalar query was some kind of "If Exists" query to test for the table.
return;
using(var cmd = new SQLiteCommand(commandText, conn))
{
using(var reader = cmd.ExecuteReader())
{
//....
}
}
}
如果列出所有可用表的模式的名称不是Tables
,则只需调用conn.GetSchema()
而不使用参数来查看所有可用的模式选项。
答案 1 :(得分:1)
IDbCommand.ExecuteScalar是底层接口方法。根据此方法的documentation:
“如果未找到结果集中第一行的第一列,则返回空引用(Visual Basic中 Nothing )。如果数据库中的值为 null ,查询返回 DBNull.Value “。
您的代码应处理任何一种情况。
但是......如果查询中指定的表不存在,则会抛出异常,就像对任何其他失败情况一样(查询中的语法错误等)。您应该使用try / catch逻辑包装所有数据库交互;您可能会对数据库执行任何操作的失败案例,并通过抛出异常将所有失败案例传达给您的应用程序代码。
try
{
var result = cmd.ExecuteScalar();
if (result == null)
{
// handle null case
}
else if (result is DbNull)
{
// handle DbNull case
}
else
{
// usable result you can cast as appropriate
}
}
catch (Exception ex)
{
// Handle all other eventualities
}
答案 2 :(得分:0)
你没有得到返回空值的那么多。在此之前,Reader
(和/或ExecuteScalar
)会向您抛出异常。抓住它并相应地处理......
try
{
if (Convert.ToInt32(cmd.ExecuteScalar()) == 0)
goto doClose; // Really? That must be complex then...
else
cmd.CommandText = sql;
reader = cmd.ExecuteReader();
}
catch(SQLiteException exp)
{
Trace.WriteLine( exp.Message);
}
答案 3 :(得分:0)
这里有两个问题: -
对于1),我不太同意先检查架构。你应该把这个Db操作真的放在一个函数中然后用try / catch包装函数并以标准方式处理(错误报告/日志等)
对于2)如果您希望,您的查询返回1行或多行,为什么要使用ExecuteScalar?为什么不使用ExecuteReader()来检索一行或多行。另外,将阅读器包装在"使用"块,以确保关闭连接/阅读器。