2013-09-21 15 views
0
 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回購),如果有人可以看看它? [email protected]:tomxuetoy/WPF_startPrograms.git爲什麼我不能直接在C#中編譯表達式和null?

上面是我的代碼,它可以正常工作。在我的情況下,cmd.ExecuteScalar()將由於SQLite表不存在而返回null。 我試圖改變它像之下,但失敗:

if (cmd.ExecuteScalar() == null) 

所以,我想知道爲什麼我不能COMPRE表達(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: 
+3

定義「失敗」 –

+1

這是一個'goto'聲明嗎? – rene

+0

你可以。什麼不工作? – shovavnik

回答

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()不帶參數的查看所有可用的模式選擇。

+0

var schema = conn.GetSchema(「Tables 「,new string [] {null,null,」testTable「}); if(schema.Rows.Count == 0) return 1; //這種方式可行 –

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); 
} 
1

IDbCommand.ExecuteScalar是基礎接口方法。按照documentation此方法:

「如果沒有找到結果集中的第一行的第一列,空引用(沒有在Visual Basic中)返回如果在數據庫中的價值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 
} 
0

這裏有兩個問題: -

  1. 如何處理上的ExecuteScalar異常,如果表不存在。
  2. 如何可能關閉連接/命令(不使用轉到 語句)

爲1),我不太上第一對架構檢查同意。你應該真的把這個Db操作放在一個函數中,然後在try/catch中包裝函數並以標準方式處理(錯誤報告/日誌等)

對於2)如果您期望,您的查詢返回1或很多行,爲什麼要使用ExecuteScalar?爲什麼不使用ExecuteReader()來檢索一個或多個行。另外,將閱讀器包裝在一個「使用」塊中,以確保關閉連接/閱讀器。

相關問題