842

I have a problem with Entity Framework in ASP.NET. I want to get the Id value whenever I add an object to database. How can I do this?

According to Entity Framework the solution is:

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

    context.Customers.Add(customer);
    context.SaveChanges();
        
    int id = customer.CustomerID;
}

This doesn't get the database table identity, but gets the assigned ID of the entity, if we delete a record from the table the seed identity will not match the entity ID.

2
  • 7
    If you just need the Id in order to use it in a foreign key relationship, you may consider instead just setting the navigational property of your dependent entity to the previously added entity. This way you don't need to bother about calling SaveChanges right away just to get the id. Further reading here. Commented Jul 22, 2018 at 21:46
  • For Entity Framework Core 3.0, add the acceptAllChangesOnSuccess parameter as true : await _context.SaveChangesAsync(true); Commented Aug 29, 2019 at 16:25

12 Answers 12

1345

It is pretty easy. If you are using DB generated Ids (like IDENTITY in MS SQL) you just need to add entity to ObjectSet and SaveChanges on related ObjectContext. Id will be automatically filled for you:

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

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

Entity framework by default follows each INSERT with SELECT SCOPE_IDENTITY() when auto-generated Ids are used.

Sign up to request clarification or add additional context in comments.

12 Comments

So you are asking wrong question. If you have a problem with exception you should ask question showing your exception (and inner exception) and code snippet causing that error.
Make sure that the Entity you are adding is a valid Entity eg., anything with a database restriction of "not null" must be filled etc.
@LadislavMrnka: What about the navigation properties of the newly-created object? They don't seem to be getting automatically populated after saving changes.
Let's consider the following scenario:table1 is supposed to generate an @@identity to use it in table2. Both table1 and table2 are supposed to be in the same transaction for e.g. one SaveChange operation must save both table's data. @@identity won't be generated unless a 'SaveChanges' is invoked. how can we address this situation?
@Djeroen: If you use database generated Id, you need to first insert those objects to database. If you need to have Ids before insertion you must build your own logic to get unique Ids before data are inserted and don't use identity column in the database.
|
234

I had been using Ladislav Mrnka's answer to successfully retrieve Ids when using the Entity Framework however I am posting here because I had been miss-using it (i.e. using it where it wasn't required) and thought I would post my findings here in-case people are looking to "solve" the problem I had.

Consider an Order object that has foreign key relationship with Customer. When I added a new customer and a new order at the same time I was doing something like this;

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

However in my case this was not required because I had a foreign key relationship between customer.Id and order.CustomerId

All I had to do was this;

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

Now when I save the changes the id that is generated for customer is also added to order. I've no need for the additional steps

I'm aware this doesn't answer the original question but thought it might help developers who are new to EF from over-using the top-voted answer for something that may not be required.

This also means that updates complete in a single transaction, potentially avoiding orphin data (either all updates complete, or none do).

12 Comments

Thanks ! IMPORTANT Best Practice Tip : var order = new Order{Customer = customer}; This shows the power of Entity Framework to assign related object and the Id will automatically be updated .
Please also mention in your answer (preferably in bold letters) that this resolves a transaction behavior. If one of the objects is failed to add, part of the transaction won't be successful. E.g. Adding person and student. Person succeed and student fails. Now person is redundant. Thank you for this great solution though!
Small update (which would have been obvious to none noobs like me) but .Add will need to be called for each object before .SaveChanges, just those 3 lines doesn't add the new record to the DB.
@JohnnyJP it should work to however many levels you want, this is definitely something EF can do. If it isn't working then my guess is that some aspect of your EF models and context are not set up correctly. Perhaps there is a missing foreign key?
@Black-Pawn-C7 When you call save EF will convert what you did in C# into SQL, since you added customer to order and then added order to the context EF knows about your customer too and will execute an SQL statement that adds both the order and the customer.
|
43

You need to reload the entity after saving changes. Because it has been altered by a database trigger which cannot be tracked by EF. SO we need to reload the entity again from the DB,

db.Entry(MyNewObject).GetDatabaseValues();

Then

int id = myNewObject.Id;

Look at @jayantha answer in below question:

How can I get Id of the inserted entity in Entity framework when using defaultValue?

Looking @christian answer in below question may help too:

Entity Framework Refresh context?

11 Comments

Hi, when I do like this , I get the compile error which says : can not resolve the properties for example Id or Name, can you help me please ?
Shouldn't have to do .GetDatabaseValues(); if you just saved your model to the DB. The ID should repopulate to the model automatically.
@QMaster Except that EF is also able to (and does) execute that very same SQL statement and populates the ID of your object. Otherwise, how is it able to save multiple dependent objects at the same time? How would it be able to GetDatabaseValues() if it doesn't know the ID of the object to look for in the database?
@vapcguy I see. Thanks for your heeds. I will check that in both versions of EF ASAP.
@vapcguy FWIW, The model gets repopulated automatically in EF Core 2.2.x.
|
29

You have to set the property of StoreGeneratedPattern to identity and then try your own code.

Or else you can also use this.

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

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

5 Comments

Same as the top voted answer.
StoreGeneratedPattern was the missing piece for me.
That's the way to go when working with ORACLE and ON-Insert Trigger,
link is broken - parked domain
Hi with Oracle I had to set the StoreGeneratedPattern in Entity - go to the model viewer, find your table and PK, select the StoreGeneratedPattern property and set to Identity. It works as above answer indicates. This is for the case where you have a trigger that populates your PK from a sequence on insert.
20

The object you're saving should have a correct Id after propagating changes into database.

1 Comment

have you seen the inner exception? ;-)
4

I come across a situation where i need to insert the data in the database & simultaneously require the primary id using entity framework. Solution :

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

Comments

4

You can get ID only after saving, instead you can create a new Guid and assign before saving.

1 Comment

Ahmet wants to get the Id AFTER save anyway. Although a good option for some scenarios, it is an overkill for this one.
3
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;

This will work.

2 Comments

Repository is not responsible for saving changes into database. It's a UnitOfWork's job.
Moreover, it's absolutely unclear what Repository is. And "this will work" is some explanation!.
3

There are two strategies:

  1. Use Database-generated ID (int or GUID)

    Cons:

    You should perform SaveChanges() to get the ID for just saved entities.

    Pros:

    Can use int identity.

  2. Use client generated ID - GUID only.

    Pros: Minification of SaveChanges operations. Able to insert a big graph of new objects per one operation.

    Cons:

    Allowed only for GUID

Comments

3

All answers are very well suited for their own scenarios, what i did different is that i assigned the int PK directly from object (TEntity) that Add() returned to an int variable like this;

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
}

so instead of creating an entire new object, you just take what you want :)

EDIT For Mr. @GertArnold :

enter image description here

9 Comments

It's not really useful to add a non-disclosed method to assign an Id. This isn't even related to Entity Framework.
@GertArnold .. i had the same question as the OP i found the answers and made it into a single line statement, and i have never heard of the term non-disclosed method care to explain ?
That just means that you don't show (disclose) everything you do. Maybe it's just not clearly described, I don't know. What I do know is that Add (if this is DbSet.Add) does not magically assign a value to EmployeeId.
Not without SaveChanges. Impossible. Unless you have some other process that assigns EmployeeId, for instance in Employee's constructor. OR you're in EF core using ForSqlServerUseSequenceHiLo. Anyway, you're not giving the whole picture.
My last remark will be: this isn't standard EF behavior. You should give more details of your environment. EF version, database brand and version, Employee class, its mapping details.
|
2

When you use EF 6.x code first

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

and initialize a database table, it will put a

(newsequentialid())

inside the table properties under the header Default Value or Binding, allowing the ID to be populated as it is inserted.

The problem is if you create a table and add the

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

part later, future update-databases won't add back the (newsequentialid())

To fix the proper way is to wipe migration, delete database and re-migrate... or you can just add (newsequentialid()) into the table designer.

2 Comments

Can you elaborate on where newsequentialid() goes? I already have database models created by hand, not using EF code first, and it doesn't fill the id becuase it isn't my primary key. Would love to find solution for that.
@josh Assuming the code first is Guid type, right click your table in Sql Server Management Studio, click the Id column, and under the Column Properties tab, inside (General), you will see Default Value or Binding. If you are creating DB tables by hand, refer to NewSequentialId or NewId. The general use case is something like when -column- is NULL, then NEWID()
1

I am using MySQL DB & I have an AUTO_INCREMENT field Id .

I was facing the same issue with EF.

I tried below lines, but it was always returning 0.

      await _dbContext.Order_Master.AddAsync(placeOrderModel.orderMaster);
      await _dbContext.SaveChangesAsync();

      int _orderID = (int)placeOrderModel.orderMaster.Id;

enter image description here But I realized my mistake and corrected it.

The Mistake I was doing: I was passing 0 in my orderMaster model for Id field

enter image description here

Solution worked: Once I removed the Id field from my orderMaster model, It started working.

enter image description here

I know it was very silly mistake, but just putting here if anyone is missing this.

1 Comment

Well, if for some reason EF inserts 0 as ID value (which shouldn't happen based on your brief description) you still get 0 as the value of the inserted record, so nothing wrong here in that part.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.