关于c#:如何在Entity框架中获取插入实体的Id?

How can I get Id of inserted entity in Entity framework?

我在ASP.NET中的实体框架有问题。每当我向数据库中添加一个对象时,我都想获取ID值。我该怎么做?


这很容易。如果您使用的是DB生成的ID(如MS SQL中的IDENTITY,则只需在相关ObjectContext上向ObjectSetSaveChanges添加实体即可。Id将自动为您填写:

1
2
3
4
5
6
7
using (var context = new MyContext())
{
  context.MyEntities.AddObject(myNewObject);
  context.SaveChanges();

  int id = myNewObject.Id; // Yes it's here
}

当使用自动生成的Id时,默认情况下,实体框架遵循每个INSERTSELECT SCOPE_IDENTITY()


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

考虑与客户具有外键关系的订单对象。当我同时添加新客户和新订单时,我正在做类似的事情;

1
2
3
4
5
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

但是在我的案例中,这不是必需的,因为我在customer.id和order.customerid之间有一个外键关系。

我要做的就是这个;

1
2
3
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

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

我知道这并不能回答最初的问题,但我认为这可能有助于开发人员谁是新的英孚从过度使用投票的答案,为一些可能不需要的东西。


保存更改后需要重新加载实体。因为它已被数据库触发器更改,而该数据库触发器不能由ef跟踪。所以我们需要从数据库重新加载实体,

1
db.Entry(MyNewObject).GetDatabaseValues();

然后

1
int id = myNewObject.Id;

看看下面问题中的@jayantha答案:

使用DefaultValue时,如何获取实体框架中插入实体的ID?

在下面的问题中寻找@Christian的答案也会有所帮助:

实体框架刷新上下文?


请参考此链接。

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

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

或者你也可以用这个。

1
2
3
4
5
6
7
using (var context = new MyContext())
{
  context.MyEntities.AddObject(myNewObject);
  context.SaveChanges();

  int id = myNewObject.Id; // Your Identity column ID
}


将更改传播到数据库后,要保存的对象应该具有正确的Id


1
2
3
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;

这行得通。


您只能在保存后获取ID,而可以在保存前创建新的GUID和分配。


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

1
2
3
4
5
6
7
8
9
10
long id;
IGenericQueryRepository<myentityclass, Entityname> InfoBase = null;
try
 {
    InfoBase = new GenericQueryRepository<myentityclass, Entityname>();
    InfoBase.Add(generalinfo);
    InfoBase.Context.SaveChanges();
    id = entityclassobj.ID;
    return id;
 }

所有答案都非常适合他们自己的场景,我做的不同之处在于,我直接从对象(tenty)分配了int pk,该对象(tenty)的add()返回到这样的int变量;

1
2
3
4
5
6
7
8
9
10
11
12
using (Entities entities = new Entities())
{
      int employeeId = entities.Employee.Add(new Employee
                        {
                            EmployeeName = employeeComplexModel.EmployeeName,
                            EmployeeCreatedDate = DateTime.Now,
                            EmployeeUpdatedDate = DateTime.Now,
                            EmployeeStatus = true
                        }).EmployeeId;

      //...use id for other work
}

因此,您不需要创建一个完整的新对象,只需获取所需的内容:)

编辑@gertarnold先生:

enter image description here


有两种策略:

  • 使用数据库生成的Id(intGUID)

    欺骗:

    您应该执行SaveChanges()以获取刚刚保存实体的Id

    赞成的意见:

    可以使用int身份。

  • 仅使用客户端生成的Id-guid。

    赞成的意见:SaveChanges操作的缩小。能够在每次操作中插入新对象的大图表。

    欺骗:

    仅允许用于GUID


  • 当您首先使用EF6.x代码时

    1
    2
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public Guid Id { get; set; }

    并初始化数据库表,它将

    1
    (newsequentialid())

    在表头默认值或绑定下的表属性中,允许在插入时填充ID。

    问题是,如果创建一个表并添加

    1
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]

    稍后,将来的更新数据库将不会添加回(newSequentialID())

    正确的方法是清除迁移,删除数据库,然后重新迁移…或者只需将(newSequentialID())添加到表设计器中。