2013-07-08 60 views
46

实体框架 - 在调用'SaveChanges'之前是否有任何方法在事务内部检索新创建的ID(标识)?实体框架 - 在交易中的'SaveChanges'之前检索ID

我需要一个第二个插入的ID,但它始终返回0 ...是由数据库生成

 ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext; 

     objectContext.Connection.Open(); 

     using (var transaction = objectContext.Connection.BeginTransaction()) 
     { 
      foreach (tblTest entity in saveItems) 
      { 
       this.context.Entry(entity).State = System.Data.EntityState.Added; 
       this.context.Set<tblTest>().Add(entity); 

       int testId = entity.TestID; 

       .... Add another item using testId 
      } 

      try 
      { 
       context.SaveChanges(); 
       transaction.Commit(); 
      } 
      catch (Exception ex) 
      { 
       transaction.Rollback(); 
       objectContext.Connection.Close(); 
       throw ex; 
      } 
     } 

     objectContext.Connection.Close(); 
+3

http://stackoverflow.com/questions/6029711/id-of-newly-added-entity-before-savechanges – Zaki

+0

哦,希望有一种方式,但谢谢。 – user1948635

回答

38

的ID行插入到表后。在插入行之前,您无法向数据库询问该值。

你有两种解决方法 - 最简单的方法是拨打SaveChanges。由于您处于交易中,因此您可以回滚,以免在获取ID后出现问题。

第二种方法不是使用IDENTITY内置的数据库,而是自己实施它们。当你有很多批量插入操作时,这可能非常有用,但它带有一个价格 - 实现起来并不是微不足道的。

编辑:SQL Server 2012有一个内置的SEQUENCE类型,可以用来代替IDENTITY列,不需要自己实现它。

+1

如果我在第一次插入后调用'SaveChanges',那么第二次插入失败 - 事务是否会将第一次插入返回? – user1948635

+6

当然,这就是交易的意义。事务中的每个操作都将在'rollback'上回滚。看看http://en.wikipedia.org/wiki/ACID – SeriousM

+0

实体中没有回滚功能。它像鸡和鸡蛋的问题。唯一的方法是执行一些纯SQL,然后向DB询问下一个Identity将会是什么。但是这是不能保证的,因为有人可以接受它。另一件事是编写SQL并插入和清空行来保留它,但是你可能会使用空的保留行。 – ppumkin

7

@zmbq是正确的,你只能在调用保存更改后才能得到id。

我的建议是你不应该依赖数据库生成的ID。 数据库应该只是你的应用程序的一个细节,而不是一个不可或缺的部分。

如果您无法解决该问题,请使用GUID作为标识符,因为它具有唯一性。 MSSQL支持GUID作为本地列类型,并且速度很快(尽管不比INT快)。

干杯

+0

不幸的是,现在更改ID字段会导致应用程序的其他方面出现问题,这意味着我试图避免的重大更改。 – user1948635

+0

但它是一个INT列,对不对?也许你可以插入一个TICK或你自己创建的唯一号码。 – SeriousM

+0

它是,但有大量的SSIS包运行在数据库上期望一个标识列... – user1948635

3

如果您TBLTEST实体连接到您要附加其他实体,你不需要有ID来创建的关系。比方说TBLTEST连接到anotherTest对象,它的方式是,在anotherTest对象必须TBLTEST对象和tblTestId属性,在这种情况下,你可以有这样的代码:

using (var transaction = objectContext.Connection.BeginTransaction()) 
    { 
     foreach (tblTest entity in saveItems) 
     { 
      this.context.Entry(entity).State = System.Data.EntityState.Added; 
      this.context.Set<tblTest>().Add(entity); 

      anotherTest.tblTest = entity; 
      .... 
     } 
    } 

提交的关系后,也可以创建和你不不需要担心ID等