首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >'Using‘语句中的Select @@Identity

'Using‘语句中的Select @@Identity
EN

Stack Overflow用户
提问于 2013-04-03 21:56:12
回答 3查看 2.3K关注 0票数 0

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

最近,我一直在转换我的代码以使用using语句,因为它们要干净得多。在我的代码中,我有一个非常简单的GetLastInsertedID函数-它返回最后插入的ID。工作版本如下:

代码语言:javascript
复制
    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语句中后不能工作的代码:

代码语言:javascript
复制
    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();行上。

我在第二段代码中做错了什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-04-03 22:37:05

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

这显示了您的实际问题和设计问题-您需要将Connection命令分开。 connection 嵌入事务,虽然SCOPE_IDENTITY()将一直工作到连接关闭;但可以创建、使用和处置命令

所以你需要一个接受connection并使用它来获取标识方法--就像这样(我没有检查它,但我认为想法应该是清晰的):

代码语言:javascript
复制
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;
    }
}

为了使用连接,您可以像这样创建辅助方法:

代码语言:javascript
复制
public static SqlCeConnection OpenDefaultConnection()
{
    SqlCeConnection conn = new SqlCeConnection(DbConnection.compact);
    conn.Open();
    return conn;
}

并像这样使用它:

代码语言:javascript
复制
...
using (SqlCeConnection conn = OpenDefaultConnection()) {
    //... do smth
    int id = GetLastInsertedID(conn);
    //... do smth
}
...
票数 0
EN

Stack Overflow用户

发布于 2013-04-03 22:04:10

@@IDENTITY documentation

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

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

票数 5
EN

Stack Overflow用户

发布于 2017-07-20 08:52:23

在我看来,它不工作的原因与using statement无关。

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

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

希望它能对你有所帮助

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15789377

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档