Sql server 如何在使用ExecuteStoreCommand(“插入”)插入记录后获取“新记录Id”

Sql server 如何在使用ExecuteStoreCommand(“插入”)插入记录后获取“新记录Id”,sql-server,asp.net-mvc,linq,asp.net-mvc-3,linq-to-entities,Sql Server,Asp.net Mvc,Linq,Asp.net Mvc 3,Linq To Entities,我使用的是MVC3、ASP.NET4.5、C、EF5、SQLServer2008R2 我想了解插入记录后获取新记录Id的最佳方法,因为PK是一个int32标识列 我目前的代码是: db.ExecuteStoreCommand("INSERT INTO Table1(Col1,Col2 ) SELECT Col1,Col2 FROM Table1 WHERE Id = {0}", myOldRecordId); command = @"SELECT IDENT_CURRENT({0}) AS

我使用的是MVC3、ASP.NET4.5、C、EF5、SQLServer2008R2

我想了解插入记录后获取新记录Id的最佳方法,因为PK是一个int32标识列

我目前的代码是:

db.ExecuteStoreCommand("INSERT INTO Table1(Col1,Col2 ) SELECT Col1,Col2 FROM Table1 WHERE Id =   {0}", myOldRecordId);
command = @"SELECT IDENT_CURRENT({0}) AS Current_Identity;";
myNewRecordId = (int)db.ExecuteStoreQuery<decimal>(command, "Table1").First();
虽然上述方法有效,但我担心其他人可能会同时将一条记录插入到同一个表中,因此检索到的NewRecordId=correct值+1

一旦通过ExecuteStoreCommand发出插入,检索新NewRecordId的最佳方法是什么

顺便说一句,出于许多原因,我需要使用原始DML,而不是通过EF使用POCO

提前谢谢

编辑

根据我对给出的建议的理解,代码将发生变化:

using(TransactionScope tran = new TransactionScope()) 
{
   db.ExecuteStoreCommand("INSERT INTO Table1(Col1,Col2 ) SELECT Col1,Col2 FROM Table1 WHERE Id =   {0}", myOldRecordId);
   command = @"SELECT SCOPE_IDENTITY ({0}) AS Current_Identity;";
   myNewRecordId = (int)db.ExecuteStoreQuery<decimal>(command, "Table1").First(); 
   tran.Complete();
}
我认为我仍然需要改变这一点,以使db.ExecuteStoreCommand和db.ExecuteStoreQuery事务感知

编辑2

经过进一步研究,我发现:

db.Connection.Open(); //db = EF DBContext
var tran = db.Connection.BeginTransaction();

db.ExecuteStoreCommand("INSERT INTO Table1(Col1,Col2 ) SELECT Col1,Col2 FROM Table1 WHERE Id =   {0}", myOldRecordId);

command = @"SELECT SCOPE_IDENTITY ({0}) AS Current_Identity;";
myNewRecordId = (int)db.ExecuteStoreQuery<decimal>(command, "Table1").First(); 

tran.Commit();
db.Connection.Close();
见:

这是从其他用户记录插入中获取新ID而不损坏的最佳方法吗


实际上,读了更多的文章后,这是老办法,TransactionScope就是办法。

很抱歉将此写在回答中而不是评论中:我认为你99%是对的,据我所知,你应该使用

scope_identity()

这里不是ident_current,而是关于获取最后一个插入id的100%

答案。您应该使用此方法。您获取的最后一个插入id是每个会话。因此,您可以从工作会话中获取最后一个插入id。如果使用正确的方法,应该不会有任何问题


如果插入一行并获取最后一个插入的id,则执行一个新的选择,您可能会遇到如您所预测的问题。

尝试使用TransactionScope,然后使用scope_标识,类似于使用TransactionScope scope=new TransactionScope TransactionScope选项{插入后获取标识的代码}谢谢。我没有使用TransactionScope。有没有可能是一个代码示例。只是有点困惑,插入和选择是进入这个还是仅仅进入选择?您使用的是实体框架吗?请阅读web应用程序中的并发问题,以及.net Framework如何与Entit等ORM一起处理它y、 …正如@Nilesh提到的,一种方法是使用事务…事务也可以在数据库服务器级别处理…Google是您最好的朋友…这两个语句都需要是作用域的一部分。只需示例代码,但不包含EF.var conn=new SqlConnectionConfigurationManager.ConnectionStrings[Test].ConnectionString;连接打开;使用TransactionScope ts=new TransactionScope TransactionScope Option.RequiresNew{var cmd=new SqlCommandInsert into tempforts value'1',conn;cmd.ExecuteNonQuery;cmd=new SqlCommandSelect scope_Identity,conn;var id=cmd.ExecuteScalar;}请参阅上面的编辑,了解我尝试的新代码,该代码采纳了您的建议。谢谢,但这与应用程序中仅TSQL答案相关,而不是在C代码中。因此,在应用程序代码中,我仍然需要进行新的选择,即使是范围_标识,除非我遗漏了一些内容。也许C代码示例可能会有所帮助。谢谢。by new sel选择最后一条插入记录的id。如通过created_date desc从my_table order中选择id;这可能会导致您描述的问题。但如果您使用scopre_identity,您应该不会有问题。再次感谢,但我要寻找的答案需要驻留在C代码中。因此,问题是如果我在我的C代码中选择scope_identity,我会吗还可以吗?是的,如果你用c代码调用它,你应该还可以。100%确定的是,你也可以编写自己的测试。例如,你可以编写一些代码,将记录不间断地插入到表中,同时你可以运行另一段代码,插入一条记录,并在1秒后获取最后一条记录id。谢谢。如何正如@gurel_kaynak所说,我担心您的回答没有说明这将在应用程序C代码中运行,而不是在DB服务器上运行TSQL。Nilesh引入了一些有趣的新构造。