MySql最后插入ID,Connector .net

20
我正在使用MySql Connector .net,并且需要获取上一个查询生成的插入ID。现在,我假设MySqlHelper.ExecuteNonQuery的返回值应该是最后一个插入ID,但它只返回1。
我使用的代码是:
int insertID = MySqlHelper.ExecuteNonQuery(Global.ConnectionString, 
"INSERT INTO test SET var = @var", paramArray);

然而,insertID始终为1。我尝试手动创建MySQL连接并打开/关闭连接,结果行为相同。


1 表示已插入 1 条记录。要获取插入的 ID,您需要进行查询。 - chance
“SET” 不是用于插入数据,而是用于更新数据的吗? - jason
你可以同时用它来进行以下两种操作:http://dev.mysql.com/doc/refman/5.5/en/insert.html - Splatbang
6个回答

115

只需使用 LastInsertedId 字段

MySqlCommand dbcmd = _conn.CreateCommand();
dbcmd.CommandText = sqlCommandString;
dbcmd.ExecuteNonQuery();
long imageId = dbcmd.LastInsertedId;

3
这是正确的答案。经过 MySql/Connector 6.3.8 的测试。 - caligari
这是一种方法,但如果您需要严格使用MySqlHelper.ExecuteNonQuery,则不适用。使用MySqlHelper的原因之一是当您希望连接器管理连接池时,正如文档中所述,一种方法是使用不将新的MySqlConnection对象作为参数传递的api重载,而是让连接器自己管理其创建。因此,这不是这种情况(我的情况)的解决方案。 - Veverke
非常感谢你,我们为一个客户的跨平台设置而苦恼不已,他们已经有了SQL Server并想要MySQL。他们使用了scope_identity,我能够在MySql实现中使用DbCommand对象转换为MySqlCommand,并获得LastInsertedId对象。同样的Scope_Identity问题只需要一行代码就解决了。真的救了我的命,非常感谢你。 - Matthew Young

5

这里的1表示查询影响的记录数,由于只插入了一行数据,所以返回1。

如果要获取插入行的ID,可以在Sqlserver中使用scope_identity()函数,在MySql中使用LAST_INSERT_ID()函数。


5

尝试使用此查询获取最后插入的id -

SELECT LAST_INSERT_ID();

然后,运行DbCommand.ExecuteReader方法以获取IDataReader -
command.CommandText = "SELECT LAST_INSERT_ID()";
IDataReader reader = command.ExecuteReader();

...并从读者那里获取信息 -

if (reader != null && reader.Read())
  long id = reader.GetInt64(0);

不要忘记关闭读取器;-)

(提示:该句话是关于IT技术的)

谢谢!这是使用事务时唯一的工作方式 ;) - Renan Franca
工作得非常好。谢谢。 - CodeFluid

4

我曾遇到同样的问题,经过一些测试,我发现问题似乎在于连接方式;你正在使用连接字符串。

当然这是为了利用自动连接池重用,但在这种情况下,它给我带来了麻烦。

对我来说最终的解决方案是创建一个新的连接, 执行插入查询, 然后执行 last_insert_id()。在同一个连接上。

如果不使用相同的连接,last_insert_id() 可能会返回任何值,我不知道为什么,但猜测它会因为不同的连接而失去轨迹。

例子:

MySqlConnection connection = new MySqlConnection(ConnectionString);
connection.Open();

int res = MySqlHelper.ExecuteNonQuery(
    connection,
    "INSERT INTO games (col1,col2) VALUES (1,2);");

object ores = MySqlHelper.ExecuteScalar(
connection,
"SELECT LAST_INSERT_ID();");

if (ores != null)
{
  // Odd, I got ulong here.
  ulong qkwl = (ulong)ores;
  int Id = (int)qkwl;
}

我希望这能帮助到某些人!

0

请尝试在代码库中使用以下可行的解决方案。

 string query = $"INSERT INTO `users`(`lastname`, `firstname`, `email`, `createdate`, `isdeleted`) " +
                $"VALUES ('{userEntity.LastName}','{userEntity.FirstName}','{userEntity.Email}','{userEntity.CreateDate}',{userEntity.IsDeleted});" +
                $"SELECT LAST_INSERT_ID();";
           var res= _db.ExecuteScalar(query);

            return (int)(UInt64)res;

0

我知道这是一个旧帖子,但我一直面临着和Snorvarg一样的问题。使用MySqlHelper时,使用连接字符串而不是Connection对象(以允许MySqlHelper使用连接池),SELECT LAST_INSERT_ID()经常会给我上一个执行的查询的ID,或者其他时间它会返回零。然后我就得再调用一次SELECT LAST_INSERT_ID()才能获得正确的ID。

我的解决方案是将正在执行的查询和调用SELECT LAST_INSERT_ID()之间的所有内容封装在TransactionScope中。这迫使MySqlHelper坚持一个连接,而不是打开两个独立的连接。

所以:

string sql = "INSERT INTO games (col1,col2) VALUES (1,2);");
string connectionString = "some connection string";

using (TransactionScope scope = new TransactionScope)
{
    int rowsAffected = MySqlHelper.ExecuteNonQuery(connectionString, sql);    
    object id = MySqlHelper.ExecuteScalar(connectionString, "SELECT LAST_INSERT_ID();");
    scope.Complete();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接