我正在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();
上会出现此错误。
第二块代码我做错了什么?
答案 0 :(得分:5)
@@ IDENTITY和SCOPE_IDENTITY将返回当前会话中任何表中生成的最后一个标识值。
我认为您的更改现在为每个using语句启动一个新会话。因此@@ IDENTITY为空。
答案 1 :(得分: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
}
...
答案 2 :(得分:0)
在我看来,它不起作用的原因与using statement
无关。
如果使用静态类来执行连接数据库的操作,例如DBHelper。在执行select @@identity
之前关闭数据库连接以及执行select @@identity
时,再次打开它会导致问题。此执行序列将导致select @@identity
的返回结果为NULL。也就是说,您不能使用DBHelper.xxx()
两次来获取自动ID,因为每次调用DBHelper.xxx()
时,都会完成打开数据库和结束数据库的过程。
我有一个解决方案,但它可能不是最好的解决方案。您可以使用select @@identity
来获得相同的结果,而不是使用select count(*) from xxx
。
希望它可以帮到你