0

我正在编写一个Sql-Server-ce应用程序C#

最近我一直在将我的代码转换为使用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();

我对第二个代码块做错了什么?

4

3 回答 3

5

来自@@IDENTITY 文档

@@IDENTITY 和 SCOPE_IDENTITY 将返回当前会话中任何表中生成的最后一个标识值。

我认为您的更改现在为每个 using 语句启动一个新会话。因此@@IDENTITY 为空。

于 2013-04-03T14:04:09.667 回答
0

首先,@@Identity将从 SQL Server 中的任何位置返回任何最后生成的 ID。很可能您需要使用它SCOPE_IDENTITY()

这显示了您的实际问题和设计问题 - 您需要将ConnectionCommand分开。连接嵌入事务并且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
}
...
于 2013-04-03T14:37:04.957 回答
0

在我看来,它不起作用的原因与using statement.

如果使用静态类来做连接数据库的操作,比如DBHelper。问题是你在执行之前关闭了数据库的连接,select @@identity当你执行时select @@identity,你再次打开它。这个执行顺序会导致返回结果select @@identity为NULL。也就是说,你不能使用DBHelper.xxx()两次来获取自动ID,因为每次调用DBHelper.xxx()都会完成打开数据库和关闭数据库的过程。

我有一个解决方案,但它可能不是最好的。代替 using select @@identity,您可以使用select count(*) from xxx来获得相同的结果。

希望它可以帮助你

于 2017-07-20T00:52:22.843 回答