Select @@Identity inside 'Using' statement
本文关键字:statement Using @@Identity inside Select | 更新日期: 2023-09-27 18:07:24
我正在C#
中编写Sql-Server-ce
应用程序。
最近我一直在转换我的代码使用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();
行。
我对第二块代码做错了什么?
来自@@IDENTITY文档:
@@IDENTITY和SCOPE_IDENTITY将返回当前会话中任何表的最后一个标识值。
我认为你的修改现在为每个using语句启动一个新的会话。因此@@IDENTITY为空
首先,@@Identity
将返回任何最后生成的ID从SQL Server的任何地方。最有可能的是,您需要使用SCOPE_IDENTITY()
。
这显示了您的实际问题和设计问题-您需要保持连接和命令分开。Connection嵌入事务,尽管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;
}
}
对于连接,您可以创建这样的helper方法:
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
}
...
在我看来,它不起作用的原因与using statement
无关。
如果使用静态类来完成连接数据库的操作,如DBHelper。这个问题是由于你在执行select @@identity
之前关闭了数据库连接,而在执行select @@identity
的时候又重新打开了数据库连接。这个执行序列将导致select @@identity
的返回结果为NULL。也就是说,您不能两次使用DBHelper.xxx()
来获取自动ID,因为每次调用DBHelper.xxx()
时,都会执行打开数据库和关闭数据库的过程。
select count(*) from xxx
而不是select @@identity
来获得相同的结果。希望对你有帮助