如何插入一条logging并使用一个SqlCommand返回新创build的ID?

我正在使用一个SqlCommand对象插入一个logging到一个自动生成的主键的表。 我如何编写命令文本,以便在使用ExecuteScalar()方法时获得新创build的ID?

INSERT INTO YourTable(val1, val2, val3 ...) VALUES(@val1, @val2, @val3...); SELECT SCOPE_IDENTITY(); 

不要忘记每个语句结尾的分号。

将下面一行添加到Sql查询的末尾…

 SELECT SCOPE_IDENTITY() 

然后在SqlCommand对象上使用ExecuteScalar方法…

 var rowCount = command.ExecuteScalar() 
 insert into Yourtable() values() SELECT SCOPE_IDENTITY() 

我刚刚运行了一个testing,并validation了使用SQL Server 2005 SP2和.Net 3.5的分号是可选的

将输出参数添加到命令对象,然后将该值设置为存储过程中的新ID。

存储过程:

 @ID AS INT OUTPUT [Insert Command] SET @ID = SCOPE_IDENTITY() 

。净:

 cmd.CommandText = "stored_procedure"; SqlParameter pID = new SqlParameter("ID", DBType.Int32, 4); pID.Direction = ParameterDirection.Output; cmd.ExecuteScalar(); int id = Convert.ToInt32(cmd.Parameters["ID"].Value.ToString()); 

不要使用@@ IDENTITY,不过看起来很简单。 它可以返回不正确的值。

 SELECT SCOPE_IDENTITY() 

似乎是明显的select。

在插入stmt后立即使用

 SELECT CAST(scope_identity() AS bigint) ---- incase you have a return result as int64 

这将返回列创build的ID /身份。

直接走出漩涡 :

如果您使用的是MS SQL,则可以在插入后使用“SELECT @@ IDENTITY作为值”来获取生成的最后一个ID

和:

@@IDENTITYSCOPE_IDENTITY返回当前会话中任何表中生成的最后一个标识值。 但是, SCOPE_IDENTITY仅在当前范围内返回值; @@IDENTITY不限于特定的范围。

编辑:正如在评论中指出的,你应该总是使用SCOPE_IDENTITY ,而不是@@IDENTITY

虽然我喜欢Dave Markle的回答,(我也看到你也这样做了,因为你把它标记为答案),如果你的数据库有触发器,审计CUD操作,并且你的审计表有一个IDENTITY列,那么这个方法可能会失败。 它将返回审计表标识的值,而不是刚刚插入的表,因为审计表是真正发生的。

在这种情况下,可以使用更通用的方法,无论是否进行任何审计,都可以在两种情况下工作。 它更罗嗦一点,但你得到你所支付的。

例:

 @"DECLARE @tmp AS TABLE ( id int ) INSERT INTO case ( caseID, partID, serialNumber, hardware, software, firmware ) OUTPUT Inserted.ID into @tmp VALUES ( @caseID, @partItemID, @serialNumber, @hardware, @software, @firmware ) Select ID from @tmp" ) 

如果你的ID是一个Guid,那么我发现这个解决scheme是最好的:

 INSERT INTO YourTable (val1, val2, val3) OUTPUT inserted.id VALUES (@val1, @val2, @val3) 

谢谢@ Scott Ivey

完整演示:

  internal static Guid InsertNote(Note note) { Guid id; using ( var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["dbconn"].ConnectionString)) { connection.Open(); using ( var command = new SqlCommand( "INSERT INTO Notes ([Title],[Text]) " + "OUTPUT inserted.id " + $"VALUES ('{title}','{text}');", connection)) { command.CommandType = CommandType.Text; var reader = command.ExecuteReader(); reader.Read(); id = reader.GetGuid(reader.GetOrdinal("id")); } connection.Close(); } return id; } 

我会build议使用存储过程,但是这是为了unit testing我们的存储库。