为什么这个 SQLite 查询 return 是假的?
Why would this SQLite query return false?
我有一个 general-purpose 方法,可以用于查看给定 table 的给定列中是否至少存在一个具有给定值的记录。但是当我这样称呼它时:
return ColumnInTableContainsStrValue("Inventory", "siteNum", NRBQConsts.currentSiteNum);
...它 returns 错误,即使 table 确实包含 "siteNum" 列为“03”的记录。这是有问题的方法:
public bool ColumnInTableContainsStrValue(String tableName, String
columnName, String valToFind)
{
ExceptionLoggingService.Instance.WriteLog("Reached
TestHHSDBUtils.ColumnInTableContainsStrValue");
int count;
string qry = String.Format("SELECT COUNT(*) FROM {0} WHERE {1} =
@soughtValue", tableName, columnName)
// TODO: temp - remove
MessageBox.Show(String.Format("In ColumnInTableContainsStrValue; qry
== {0}; valToFind == {1}", qry, valToFind));
try
{
using (SQLiteConnection con = new
SQLiteConnection(HHSUtils.GetDBConnection()))
{
con.Open();
SQLiteCommand cmd = new SQLiteCommand(qry, con);
cmd.Parameters.Add(new SQLiteParameter("soughtValue",
valToFind));
count = (int)cmd.ExecuteScalar();
}
}
catch (Exception ex)
{
String msgInnerExAndStackTrace = String.Format(
"{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message,
ex.InnerException, ex.StackTrace);
ExceptionLoggingService.Instance.WriteLog(String.Format("From
TestHHSDBUtils.ColumnInTableContainsStrValue: {0}",
msgInnerExAndStackTrace));
return false;
}
return count > 0;
}
我在上述方法中的临时 MessageBox.Show() 调用显示:
因此,一旦查询 arg 从 @soughtValue 转换为 valToFind ("03"),查询应为:
SELECT COUNT(*) FROM Inventory WHERE siteNum = "03"
上面的查询在 LINQPad 中确实按预期工作:
那么为什么它在 "real life" 中失败了?
注意: ColumnInTableContainsStrValue() 中的 catch 块未捕获任何内容 - 日志文件 diesbzg 中没有任何内容。
更新
更改 catch 块以捕获 SQLiteException(代替通用异常)后,我得到了这个:
日期:2009 年 4 月 8 日 10:01:28 下午
消息:来自 frmMain.ProcessNewDelivery:InvalidCastException;内例:;堆栈跟踪:在 HHS.TestHHSDBUtils.ColumnInTableContainsStrValue(String tableName, String columnName, String valToFind)
在 HHS.frmMain.SiteInventoryHasBeenFetched()
在 HHS.frmMain.ProcessNewDelivery()
在 HHS.frmMain.menuItemFILE_NewDelivery_Click(对象发送者,EventArgs e)
在 System.Windows.Forms.MenuItem.OnClick(EventArgs e)
在 System.Windows.Forms.Menu.ProcessMnuProc(控制 ctlThis、WM wm、Int32 wParam、Int32 lParam)
在 System.Windows.Forms.Form.WnProc(WM wm, Int32 wParam, Int32 lParam)
在 System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
在 Microsoft.AGL.Forms.EVL.EnterMainLoop(IntPtr hwnMain)
在 System.Windows.Forms.Application.Run(形式调频)
在 HHS.Program.Main()
也许我必须用引号将 arg 括起来?
在 SQLite 中,ExecuteScalar
的结果是 Int64
。
所以从技术上讲,您的查询应该失败并显示 Invalid Cast Exception
(在 'real life' 和 LinqPad 中)
您可以验证这一点,将对 ExecuteScalar
的调用更改为
object result = cmd.ExecuteScalar();
result.GetType().Dump();
因此,您只需将 count
的数据类型更改为 long 并将 return 值从 ExecuteScalar 转换为 long。
您在日志文件中看不到任何内容的原因仍然是个谜。
我有一个 general-purpose 方法,可以用于查看给定 table 的给定列中是否至少存在一个具有给定值的记录。但是当我这样称呼它时:
return ColumnInTableContainsStrValue("Inventory", "siteNum", NRBQConsts.currentSiteNum);
...它 returns 错误,即使 table 确实包含 "siteNum" 列为“03”的记录。这是有问题的方法:
public bool ColumnInTableContainsStrValue(String tableName, String
columnName, String valToFind)
{
ExceptionLoggingService.Instance.WriteLog("Reached
TestHHSDBUtils.ColumnInTableContainsStrValue");
int count;
string qry = String.Format("SELECT COUNT(*) FROM {0} WHERE {1} =
@soughtValue", tableName, columnName)
// TODO: temp - remove
MessageBox.Show(String.Format("In ColumnInTableContainsStrValue; qry
== {0}; valToFind == {1}", qry, valToFind));
try
{
using (SQLiteConnection con = new
SQLiteConnection(HHSUtils.GetDBConnection()))
{
con.Open();
SQLiteCommand cmd = new SQLiteCommand(qry, con);
cmd.Parameters.Add(new SQLiteParameter("soughtValue",
valToFind));
count = (int)cmd.ExecuteScalar();
}
}
catch (Exception ex)
{
String msgInnerExAndStackTrace = String.Format(
"{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message,
ex.InnerException, ex.StackTrace);
ExceptionLoggingService.Instance.WriteLog(String.Format("From
TestHHSDBUtils.ColumnInTableContainsStrValue: {0}",
msgInnerExAndStackTrace));
return false;
}
return count > 0;
}
我在上述方法中的临时 MessageBox.Show() 调用显示:
因此,一旦查询 arg 从 @soughtValue 转换为 valToFind ("03"),查询应为:
SELECT COUNT(*) FROM Inventory WHERE siteNum = "03"
上面的查询在 LINQPad 中确实按预期工作:
那么为什么它在 "real life" 中失败了?
注意: ColumnInTableContainsStrValue() 中的 catch 块未捕获任何内容 - 日志文件 diesbzg 中没有任何内容。
更新
更改 catch 块以捕获 SQLiteException(代替通用异常)后,我得到了这个:
日期:2009 年 4 月 8 日 10:01:28 下午 消息:来自 frmMain.ProcessNewDelivery:InvalidCastException;内例:;堆栈跟踪:在 HHS.TestHHSDBUtils.ColumnInTableContainsStrValue(String tableName, String columnName, String valToFind) 在 HHS.frmMain.SiteInventoryHasBeenFetched() 在 HHS.frmMain.ProcessNewDelivery() 在 HHS.frmMain.menuItemFILE_NewDelivery_Click(对象发送者,EventArgs e) 在 System.Windows.Forms.MenuItem.OnClick(EventArgs e) 在 System.Windows.Forms.Menu.ProcessMnuProc(控制 ctlThis、WM wm、Int32 wParam、Int32 lParam) 在 System.Windows.Forms.Form.WnProc(WM wm, Int32 wParam, Int32 lParam) 在 System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam) 在 Microsoft.AGL.Forms.EVL.EnterMainLoop(IntPtr hwnMain) 在 System.Windows.Forms.Application.Run(形式调频) 在 HHS.Program.Main()
也许我必须用引号将 arg 括起来?
在 SQLite 中,ExecuteScalar
的结果是 Int64
。
所以从技术上讲,您的查询应该失败并显示 Invalid Cast Exception
(在 'real life' 和 LinqPad 中)
您可以验证这一点,将对 ExecuteScalar
的调用更改为
object result = cmd.ExecuteScalar();
result.GetType().Dump();
因此,您只需将 count
的数据类型更改为 long 并将 return 值从 ExecuteScalar 转换为 long。
您在日志文件中看不到任何内容的原因仍然是个谜。