2013-04-03 69 views
0

我在C#中編寫了一個Sql-Server-ce應用程序。在'使用'語句中選擇@@ Identity

最近我一直在將我的代碼轉換爲使用using語句,因爲它們更清晰。在我的代碼中,我有一個非常簡單的GetLastInsertedID函數 - 它返回最後插入的ID。工作版本如下:

public static int GetLastInsertedID() 
    { 
     int key = 0; 
     try 
     { 
      SqlCeCommand cmd = new SqlCeCommand("SELECT CONVERT(int, @@IDENTITY)", DbConnection.ceConnection); 
      key = (int)cmd.ExecuteScalar(); 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show("Could not get last inserted ID. " + ex.Message); 
      key = 0; 
     } 
     return key; 
    } 

下面是不工作,一旦我把它包在using語句代碼:

public static int GetLastInsertedID() 
    { 
     int key = 0; 
     try 
     { 
      using (SqlCeConnection conn = new SqlCeConnection(DbConnection.compact)) 
      { 
       conn.Open(); 
       using (SqlCeCommand cmd = new SqlCeCommand("SELECT CONVERT(int, @@IDENTITY)", conn)) 
        key = (int)cmd.ExecuteScalar(); 
      } 
     } 
     catch (Exception ex) 
     { 
      MessageBox.Show("Could not get last inserted ID. " + ex.Message); 
      key = 0; 
     } 
     return key; 
    } 

是我得到的是specified cast is not valid錯誤。雖然這個錯誤通常是不言自明的,但我不明白爲什麼我會在第二塊代碼中獲得它,但不是第一塊。該錯誤發生在行key = (int)cmd.ExecuteScalar();上。

我在做什麼錯第二塊代碼?

+0

「不行」你是什麼意思?它是否會拋出異常?如果我不得不猜測我會說一些東西被過早地處理掉了。 – Clint

+0

對不起,noob錯誤沒有發佈錯誤。它被指定爲「無效」。我編輯了這個問題。 –

+0

對不起,沒有看到您的評論!但無論如何都要在'key =(int)cmd.ExecuteScalar();'處放置一個斷點,將該命令放在監視窗口中,並檢查出現的類型。看起來,由於某種原因,儘管轉換,它不是一個整數。那麼你可能會更接近找出發生了什麼事情。 –

回答

0

首先,@@Identity將從SQL Server中的任何位置返回任何最後生成的ID。很可能你需要使用SCOPE_IDENTITY()來代替。

這說明你的實際問題和設計問題 - 你需要保持連接命令分開。 連接嵌入事務,但SCOPE_IDENTITY()將工作,直到連接關閉; 命令可以創建,使用和處置。

所以你需要方法,它接受connection並用它來獲得身份 - 這樣的事情(沒有檢查,但認爲想法應該是清楚的):

public static int GetLastInsertedID(DbConnection connection) 
{ 
    try 
    { 
     string query = "SELECT CONVERT(int, SCOPE_IDENTITY())"; 
     using (SqlCeCommand cmd = new SqlCeCommand(query, conn)) { 
      return (int)cmd.ExecuteScalar(); 
     } 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show("Could not get last inserted ID. " + ex.Message); 
     return 0; 
    } 
} 

對於您可以創建助手連接工作方法是這樣的:

public static SqlCeConnection OpenDefaultConnection() 
{ 
    SqlCeConnection conn = new SqlCeConnection(DbConnection.compact); 
    conn.Open(); 
    return conn; 
} 

而且使用這樣的:

... 
using (SqlCeConnection conn = OpenDefaultConnection()) { 
    //... do smth 
    int id = GetLastInsertedID(conn); 
    //... do smth 
} 
... 
+0

美麗的解決方案! –

+0

SQL Server Compact – ErikEJ

+0

中沒有Scope_identity()完全錯過了,但模式仍然可用 – Lanorkin

5

@@IDENTITY documentation

@@ IDENTITY和SCOPE_IDENTITY將返回在當前會話中的任何表內所生成的最後一個標識值。

我認爲您的更改現在爲每個使用語句啓動一個新的會話。因此@@ IDENTITY爲空。

+0

啊。所以我不能以這種方式使用'using'語句? –

+0

您必須在同一個using語句中執行插入操作和@@ IDENTITY。 – flup

+0

該死的,這將使我的'插入'功能更詳細... –

0

在我看來,它不起作用的原因與using statement無關。

如果使用靜態類來執行連接數據庫的操作,如DBHelper。在執行select @@identity之前關閉數據庫連接以及執行select @@identity時,會再次打開該問題。該執行序列將導致select @@identity的返回結果爲NULL。也就是說,您不能使用DBHelper.xxx()兩次來獲取自動ID,因爲每次調用DBHelper.xxx()時,都會完成打開數據庫和關閉數據庫的過程。

我有一個解決方案,但它可能不是最好的。而不是使用select @@identity,您可以使用select count(*) from xxx獲得相同的結果。

希望它能幫助你