【问题标题】:How to get a "New Record Id" after inserting a record using ExecuteStoreCommand("INSERT使用 ExecuteStoreCommand("INSERT) 插入记录后如何获取“新记录 ID”
【发布时间】:2014-11-13 12:54:09
【问题描述】:

我正在使用 MVC3、ASP.NET4.5、C#、EF5、SQL SERVER 2008 R2。

我想了解插入记录后获取“新记录 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 = 正确值 + 1。

一旦通过 ExecuteStoreCommand 发出“INSERT”,检索新的 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”事务感知。

EDIT2

经过更多研究,我发现了这一点:

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();

见:Reference

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

实际上已经阅读更多,这是旧方法,“TransactionScope”是要走的路。

【问题讨论】:

  • 尝试使用TransasctionScope,然后使用scope_identity() 类似using (TransactionScope scope = new TransactionScope(TransactionScopeOptions) { your code to get identity after insert }
  • 谢谢。我没有使用“TransactionScope”。任何代码示例的机会。只是有点困惑是 INSERT 和 SELECT 进入这个还是只是 SELECT?
  • 你在使用Entity Framework吗?请阅读一般 Web 应用程序中的并发问题以及 .net 框架如何与 Entity 等 ORM 一起处理它,正如 @Nilesh 提到的一种方法是使用事务...事务可以在数据库服务器级别也是...Google 是您最好的朋友...
  • 这两个语句都需要成为范围的一部分。只是示例代码,但没有 EF。 var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["Test"].ConnectionString); conn.Open(); using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew)) { var cmd = new SqlCommand("Insert into tempforts values('1')", conn); cmd.ExecuteNonQuery(); cmd = new SqlCommand("Select scope_Identity()",conn); var id = cmd.ExecuteScalar(); }
  • 请参阅上面的编辑,了解我尝试的新代码,其中包含您的建议。

标签: sql-server asp.net-mvc linq asp.net-mvc-3 linq-to-entities


【解决方案1】:

很抱歉在答案而不是评论中写了这个:我认为你 99% 是对的,据我了解,你应该使用

scope_identity()

而不是 ident_current,达到 100%

【讨论】:

  • 谢谢。但是,根据@gurel_kaynak,我担心您的回答并未说明这将在应用程序 C# 代码中运行,而不是在数据库服务器上的 TSQL 中运行。 Nilesh 引入了一些有趣的新结构。
【解决方案2】:

有一个关于获取最后一个插入 id here 的答案。你应该使用这种方法。您获得的最后一个插入 ID 是每个会话。因此,您从工作会话中获得了最后插入的 id。如果您使用正确的方法,应该不会有任何问题。

如果您插入一行并获取最后插入的 id,您执行新的 SELECT 可能会遇到您已经预测的问题。

【讨论】:

  • 感谢您,但这仅与 TSQL 答案有关,而不是在应用程序中的 C# 代码中。因此,在应用程序代码中,即使是“scope_identity()”,我仍然需要执行新的 SELECT,除非我遗漏了什么。也许 C# 代码示例可能会有所帮助。谢谢。
  • 通过new select Iment选择最后插入的记录的id。就像“从 my_table order by created_date desc 中选择 id;”这可能会导致您描述的问题。但是如果你使用 scopre_identity() 你应该没问题。
  • 再次感谢,但我正在寻找的答案需要存在于 C# 代码中。所以问题是如果我在我的 C# 代码中“选择 scope_identity”,我还可以吗?
  • 是的,如果您从您的 c# 代码中调用它,您应该仍然可以。 100% 确定,您也可以编写自己的测试。例如,您可以编写一些代码不停地向表中插入记录,同时您可以运行另一段代码,插入一条记录并在 1 秒后获取最后一条记录 id。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-08
  • 2016-11-26
  • 2018-11-06
  • 2010-10-10
  • 2017-02-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多