如何在Entity框架中获取插入实体的Id?

ahm*_*met 575 c# entity entity-framework

我在Asp.net中遇到了Entity Framework的问题.每当我将对象添加到数据库时,我想获取Id值.我怎样才能做到这一点?

Lad*_*nka 938

这很容易.如果您正在使用DB生成的ID(如IDENTITY在MS SQL),你只需要实体增加ObjectSetSaveChanges对相关ObjectContext.Id将自动为您填写:

using (var context = new MyContext())
{
  context.MyEntities.Add(myNewObject);
  context.SaveChanges();

  int id = myNewObject.Id; // Yes it's here
}
Run Code Online (Sandbox Code Playgroud)

默认情况下,实体框架遵循各INSERTSELECT SCOPE_IDENTITY()时自动生成的Id用于秒.

  • 所以你问的是错误的问题.如果您遇到异常问题,您应该提出问题,显示您的异常(和内部异常)和导致该错误的代码段. (34认同)
  • @Djeroen:如果使用数据库生成的Id,则需要先将这些对象插入数据库.如果在插入之前需要有ID,则必须构建自己的逻辑以在插入数据之前获取唯一ID并且不在数据库中使用标识列. (6认同)
  • @LadislavMrnka:新创建的对象的导航属性如何?保存更改后,它们似乎不会自动填充. (4认同)
  • 让我们考虑以下场景:table1应该生成一个@@ identity以在table2中使用它.table1和table2都应该在同一个事务中,例如一个SaveChange操作必须保存两个表的数据.除非调用"SaveChanges",否则不会生成@@ identity.我们怎样才能解决这种情况? (4认同)
  • 确保您要添加的实体是有效实体,例如,必须填写数据库限制为"非空"的任何内容. (3认同)
  • 当人们问问题并且没有标记正确答案时,我讨厌它 (2认同)

mar*_*k_h 105

我一直在使用Ladislav Mrnka的答案,在使用实体框架时成功检索ID,但是我在这里发帖是因为我错过了使用它(即在不需要的地方使用它)并认为我会在此发布我的发现 -案例人们正在寻求"解决"我遇到的问题.

考虑与Customer具有外键关系的Order对象.当我在同一时间添加新客户和新订单时,我正在做这样的事情;

var customer = new Customer(); //no Id yet;
var order = new Order(); //requires Customer.Id to link it to customer;
context.Customers.Add(customer);
context.SaveChanges();//this generates the Id for customer
order.CustomerId = customer.Id;//finally I can set the Id
Run Code Online (Sandbox Code Playgroud)

但是在我的情况下,这不是必需的,因为我在customer.Id和order.CustomerId之间有一个外键关系

我所要做的就是这个;

var customer = new Customer(); //no Id yet;
var order = new Order{Customer = customer}; 
context.SaveChanges();//adds customer.Id to customer and the correct CustomerId to order
Run Code Online (Sandbox Code Playgroud)

现在,当我保存更改时,为客户生成的ID也会添加到订单中.我不需要额外的步骤

我知道这并没有回答原来的问题,但认为这可能会帮助EF新手的开发人员过度使用最高投票的答案,而这些答案可能并不需要.

  • 谢谢 !重要事项最佳实践提示:var order = new Order {Customer = customer}; 这显示了实体框架分配相关对象的能力,并且ID将自动更新. (7认同)
  • 还请在您的回答中提及(最好用粗体字母)这可以解决交易行为。如果其中一个对象添加失败,则部分交易将不会成功。例如添加人和学生。个人成功,学生失败。现在人是多余的。不过还是感谢您提供了这个出色的解决方案! (4认同)

QMa*_*ter 32

您需要在savechanges之后重新加载实体.因为它已被EF无法跟踪的数据库触发器更改.所以我们需要再次从数据库重新加载实体,

db.Entry(MyNewObject).GetDatabaseValues();
Run Code Online (Sandbox Code Playgroud)

然后

int id = myNewObject.Id;
Run Code Online (Sandbox Code Playgroud)

请看以下问题中的@jayantha答案:

使用defaultValue时,如何在Entity框架中获取插入实体的Id?

在下面的问题中看@christian答案也可能有所帮助:

实体框架刷新上下文?

  • 不应该做`.GetDatabaseValues();`如果您刚刚将模型保存到数据库中.ID应自动重新填充到模型中. (3认同)
  • @QMaster除了EF还能够(并且确实)执行完全相同的SQL语句并填充对象的ID.否则,它如何能够同时保存多个依赖对象?如果它不知道要在数据库中查找的对象的ID,它将如何能够"GetDatabaseValues()"? (3认同)
  • 嗨,当我这样做时,我得到编译错误,说:无法解析例如Id或Name的属性,你能帮我吗? (2认同)
  • @vapcguy我明白了.谢谢你的关注.我将在两个版本的EF ASAP中检查. (2认同)
  • @vapcguy FWIW,该模型在 EF Core 2.2.x 中自动重新填充。 (2认同)

Azh*_*uri 16

请参阅此链接.

http://www.ladislavmrnka.com/2011/03/the-bug-in-storegeneratedpattern-fixed-in-vs-2010-sp1/

您必须将StoreGeneratedPattern的属性设置为identity,然后尝试自己的代码.

否则你也可以使用它.

using (var context = new MyContext())
{
  context.MyEntities.AddObject(myNewObject);
  context.SaveChanges();

  int id = myNewObject.Id; // Your Identity column ID
}
Run Code Online (Sandbox Code Playgroud)

  • 与最高投票的答案相同. (7认同)
  • "StoreGeneratedPattern"对我来说是个缺失的部分. (2认同)

Sno*_*ear 12

Id在将更改传播到数据库之后,您要保存的对象应该是正确的.

  • 你见过内在的例外吗?;-) (27认同)

小智 5

我遇到了一种情况,我需要在数据库中插入数据并同时使用实体框架需要主 ID。解决方案 :

long id;
IGenericQueryRepository<myentityclass, Entityname> InfoBase = null;
try
 {
    InfoBase = new GenericQueryRepository<myentityclass, Entityname>();
    InfoBase.Add(generalinfo);
    InfoBase.Context.SaveChanges();
    id = entityclassobj.ID;
    return id;
 }
Run Code Online (Sandbox Code Playgroud)


小智 5

您只能在保存后获取ID,而是可以在保存之前创建新的Guid并进行分配.