如何使用实体框架检索插入实体的ID?

我有一个问题与实体框架在ASP.NET.我想得到Id值每当我添加一个对象到数据库。我怎么能做到这一点?

根据实体框架,解决方案是:

using (var context = new EntityContext())
{
var customer = new Customer()
{
Name = "John"
};


context.Customers.Add(customer);
context.SaveChanges();
        

int id = customer.CustomerID;
}

这不会获取数据库表标识,但会获取实体的分配ID,如果我们从表中删除一条记录,种子标识将与实体ID不匹配。

589987 次浏览

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

这很简单。如果您使用的是数据库生成的ID(如MSSQL中的IDENTITY),您只需在相关的ObjectContext上将实体添加到ObjectSetSaveChangesId将自动为您填充:

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


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

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

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

或者你也可以用这个。

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


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

保存更改后需要重新加载实体。因为它已被EF无法跟踪的数据库触发器更改。所以我们需要从数据库重新加载实体,

db.Entry(MyNewObject).GetDatabaseValues();

然后

int id = myNewObject.Id;

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

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

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

实体框架刷新上下文?

我遇到了一种情况,我需要在数据库中插入数据,同时需要使用实体框架的主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;
}
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;

这将工作。

我一直在使用拉迪斯拉夫·姆兰卡的回答在使用实体框架时成功检索ID,但我在这里发布是因为我错过了使用它(即在不需要的地方使用它),并认为我会在这里发布我的发现,以防人们希望“解决”我遇到的问题。

考虑一个与客户有外键关系的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

然而,在我的情况下,这不是必需的,因为我有一个外键关系,客户ID和订单。

我所要做的就是这个;

var customer = new Customer(); //no Id yet;
var order = new Order{Customer = customer};
context.Orders.Add(order);
context.SaveChanges();//adds customer.Id to customer and the correct CustomerId to order

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

我知道这并不能回答最初的问题,但我认为这可能有助于EF新手的开发人员避免过度使用投票最多的答案来解决可能不需要的问题。

这也意味着更新在单个事务中完成,可能会避免孤儿数据(要么所有更新完成,要么没有更新完成)。

您只能在保存后获取ID,相反,您可以在保存前创建一个新的Guid并分配。

当您首先使用EF 6. x代码时

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

并初始化数据库表,它将把一个

(newsequentialid())

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

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

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

之后,未来的update-数据库将不会添加回(newequentialid())

正确的解决方法是擦除迁移、删除数据库并重新迁移…或者您可以将(newequentialid())添加到表设计器中。

有两种策略:

  1. 使用数据库生成的IDintGUID

    缺点:

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

    优点:

    可以使用int身份。

  2. 使用客户端生成的ID-仅限GUID。

    优点: SaveChanges操作的缩小。 能够在每个操作中插入一个新对象的大图。

    缺点:

    仅允许GUID

所有的答案都非常适合自己的场景,我所做的不同之处在于,我直接从对象(TEntity)分配了int PK,Add()像这样返回到一个int变量;

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先生:

在此处输入图片描述