797

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.

TylerH
  • 20,799
  • 66
  • 75
  • 101
ahmet
  • 8,003
  • 3
  • 15
  • 3
  • 4
    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](https://learn.microsoft.com/en-us/ef/core/saving/related-data). – Felix K. Jul 22 '18 at 21:46
  • For Entity Framework Core 3.0, add the acceptAllChangesOnSuccess parameter as true : await _context.SaveChangesAsync(true); – Mike Aug 29 '19 at 16:25

12 Answers12

1270

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.

ninbit
  • 530
  • 6
  • 24
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • 37
    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. – Ladislav Mrnka Mar 06 '11 at 20:09
  • 4
    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. – fran Jun 03 '11 at 09:35
  • 4
    @LadislavMrnka: What about the navigation properties of the newly-created object? They don't seem to be getting automatically populated after saving changes. – Isaac Kleinman Nov 11 '14 at 18:21
  • Actually seems to be lazily loading. – Isaac Kleinman Nov 11 '14 at 18:33
  • 4
    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? – Arash Nov 23 '14 at 23:09
  • A foreign key scenario will be listed as a property of "myNewObject". You simply add all objects required to all the required tables, referencing eachother if required before saving. – DFTR Feb 25 '15 at 19:41
  • And how if I add more than one new object? If I do, for example, 3 AddObject in a loop, how can I retrieve the 3 new IDs? – Piero Alberto Mar 18 '15 at 07:41
  • 1
    There is no way, to get the Id before the SaveChanges(), right? because i need a list of all the inserted object and i dont want to save for every object. – Djeroen Dec 02 '15 at 18:19
  • 8
    @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. – Ladislav Mrnka Dec 03 '15 at 14:12
  • 5
    I hate it when people ask questions and do not mark any correct answer – Shadi Alnamrouti Nov 21 '16 at 09:58
  • If I edit `myNewObject` after `context.SaveChanges();` and then invoke `context.SaveChanges();` again, will the change be saved in the database? – Abubakar Ahmad Mar 28 '18 at 12:31
  • will this work if my primary key and auto generated ID is a guid? I know this works with ID because haven't tried with a auto generated GUID. – CyberNinja Mar 02 '20 at 15:29
219

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).

mark_h
  • 5,233
  • 4
  • 36
  • 52
  • 16
    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 . – LA Guy 88 Jul 09 '17 at 19:06
  • Thanks for this additional information to the answer. Was very helpful in saving a DB roundtrip when using EF. – Prasad Korhale Aug 13 '19 at 00:29
  • Thank you so much for this. This is exactly what I was looking for. I just believed there could be a way better than calling "SaveChanges" two times – Josh Oct 30 '19 at 15:53
  • 3
    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! – Imran Faruqi Feb 05 '20 at 18:24
  • Thanks a lot for this answer, this was exactly my requirement by the Id. I had one data-model which required a foreign key of other data-model. – DaminiVyas Sep 03 '20 at 05:17
  • 1
    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. – Vereonix Oct 13 '20 at 14:45
  • @Vereonix you are indeed correct. I've updated the code to include the add. I'm surprised nobody pointed this out before? – mark_h Oct 14 '20 at 12:23
  • That helped thanks. Got my first bit working after quite a few hours. Was wondering if you ever got it working for 3 levels?: e.g. Customer -> Orders -> OrderItems. Cant get that to work right now.... – JohnnyJP Apr 21 '21 at 01:53
  • 1
    @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? – mark_h Apr 21 '21 at 08:28
  • @mark_h wouldn't you have to add customer as well though otherwise it won't update or am I not getting something? (btw. was looking for exactly this) – Black-Pawn-C7 Dec 13 '22 at 17:05
  • 1
    @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. – mark_h Dec 14 '22 at 08:39
  • Its document: https://learn.microsoft.com/en-us/ef/core/saving/related-data – n0099 Feb 09 '23 at 10:47
41

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?

QMaster
  • 3,743
  • 3
  • 43
  • 56
  • 2
    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 ? – Morteza Azizi Oct 17 '14 at 05:41
  • 1
    @MortezaAzizi It seems to be an error of not handled or null property issue but can you please more explain or write some snippet of code? – QMaster Oct 18 '14 at 08:54
  • 3
    Shouldn't have to do `.GetDatabaseValues();` if you just saved your model to the DB. The ID should repopulate to the model automatically. – vapcguy Sep 10 '18 at 23:05
  • You absolutely can get the Id of an Identity or other Database Generated identifier. `SELECT @@identity` as part of your SQL statement will return the ID of the last inserted column. – krillgar Sep 25 '18 at 18:38
  • @krillgar you right, But this is about adding a new object(record) with EF, not pure TSQL. To get @@identity value You need to use a Stored Procedure or run Raw SQL with SqlQuery function. Otherwise, if you insert a new record from EF how you will get @@identity value? – QMaster Sep 26 '18 at 00:51
  • @vapcguy I didn't try from EF6 but in EF5 I saw repopulating the model not happened in many cases. – QMaster Sep 26 '18 at 00:54
  • 3
    @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? – krillgar Sep 26 '18 at 10:26
  • @krillgar I'm not specialist in EF and I didn't try to check EF source to find its strategy to track changes as you asked how EF be able to GetDatabaseValues() without knowing the ID? Maybe it tracks with another temporary ID or another solution. Please attention, I upvoted Ladislav Mrnka answer as an acceptable answer and I wanted to describe solution about some scenarios I faced before. I couldn't publish answer as a comment Comprehensible, so I decided to post it as another answer. Can you explain what is the problem with GetDatabaseValues() when we couldn't get the ID in some scenarios? – QMaster Sep 26 '18 at 12:29
  • @QMaster As I've mostly worked with EF6 I can't speak to EF5. `.GetDatabaseValues()` is likely fine for that; obviously it worked for you. Just wanted to say-at least for EF6-it does populate back into the model automatically, making it no longer required now-again, at least for EF6, making it just be unnecessary code, is all. – vapcguy Sep 26 '18 at 22:30
  • 2
    @vapcguy I see. Thanks for your heeds. I will check that in both versions of EF ASAP. – QMaster Sep 27 '18 at 21:35
  • 2
    @vapcguy FWIW, The model gets repopulated automatically in EF Core 2.2.x. – slasky Feb 21 '19 at 19:15
25

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
}
Machavity
  • 30,841
  • 27
  • 92
  • 100
Azhar Mansuri
  • 665
  • 1
  • 7
  • 22
  • 7
    Same as the top voted answer. – Lewis86 Feb 22 '18 at 17:56
  • 3
    `StoreGeneratedPattern` was the missing piece for me. – BurnsBA Apr 02 '18 at 12:56
  • 1
    That's the way to go when working with ORACLE and ON-Insert Trigger, – Karl Oct 13 '18 at 09:31
  • link is broken - parked domain – t.durden Sep 05 '19 at 13:35
  • 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. – Rob Feb 10 '20 at 18:21
19

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

Snowbear
  • 16,924
  • 3
  • 43
  • 67
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;
 }
Mr Kunal
  • 49
  • 1
  • 2
4

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

4

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

IteratioN7T
  • 363
  • 8
  • 21
  • 3
    It's not really useful to add a non-disclosed method to assign an Id. This isn't even related to Entity Framework. – Gert Arnold Sep 12 '18 at 20:48
  • 1
    @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 ? – IteratioN7T Sep 13 '18 at 08:44
  • 3
    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`. – Gert Arnold Sep 13 '18 at 10:04
  • @GertArnold i dint say or state that anything happens magically, i took what i wanted from the [object](https://msdn.microsoft.com/en-us/library/system.data.entity.dbset.add(v=vs.113).aspx) that add returns? is that something i am doing it wrong.. if i am wrong please elaborate or else i would presume that your statements passive. – IteratioN7T Sep 14 '18 at 08:08
  • If you add an entity to a DbSet its Id isn't changed. `EmployeeId` will be 0. – Gert Arnold Sep 14 '18 at 08:13
  • It does give / returns me the id ( never 0 or null ) of newly created record and to be clear this snippet is working perfectly on my project. So i think it serves my purpose. – IteratioN7T Sep 14 '18 at 08:18
  • 3
    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. – Gert Arnold Sep 14 '18 at 09:12
  • @GertArnold for you i edited the answer see for your self and yes i did it without SaveChanges, without EF Core! – IteratioN7T Sep 14 '18 at 11:24
  • 3
    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. – Gert Arnold Sep 14 '18 at 11:52
3
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;

This will work.

Saket Choubey
  • 916
  • 6
  • 11
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

Vladyslav Furdak
  • 1,765
  • 2
  • 22
  • 46
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.

Jeff
  • 810
  • 8
  • 18
  • 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 Jan 09 '20 at 20:52
  • 1
    @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](https://learn.microsoft.com/en-us/sql/t-sql/functions/newsequentialid-transact-sql?view=sql-server-ver15) or [NewId](https://learn.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql?view=sql-server-ver15). The general use case is something like `when -column- is NULL, then NEWID()` – Jeff Jan 20 '20 at 22:02
0

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.

Sandeep Nandey
  • 394
  • 1
  • 6
  • 19