我正在用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();行上。
我在第二段代码中做错了什么?
发布于 2013-04-03 22:37:05
首先,@@Identity将从SQL Server中的任何位置返回任何最后生成的ID。最有可能的是,您需要使用SCOPE_IDENTITY()。
这显示了您的实际问题和设计问题-您需要将Connection和命令分开。 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;
}
}为了使用连接,您可以像这样创建辅助方法:
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-03 22:04:10
从@@IDENTITY documentation
@@IDENTITY和SCOPE_IDENTITY将返回当前会话中任意表中生成的最后一个标识值。
我认为您的更改现在为每个using语句启动了一个新会话。因此@@IDENTITY为null。
发布于 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来获得相同的结果。
希望它能对你有所帮助
https://stackoverflow.com/questions/15789377
复制相似问题