Back to FAQs

How to get an id of a saved entity in Entity Framework?

EF 6 and EF Core both, automatically populates the DB-generated Id properties (primary key or foreign key) when you call the SaveChanges() method. For example, consider the following Student entity.

public class Student
{
    public int StudentID { get; set; }
    public string StudentName { get; set; }
    public DateTime? DateOfBirth { get; set; }
    public decimal Height { get; set; }
    public float Weight { get; set; }
}

Now, when you add a new Student and call SaveChanges() method, EF will assign a newly generated id to the StudentID property.

using(var context = new SchoolContext())
{             
     var std = new Student(){ StudentName = "Steve" };
     context.Add(std);
     context.SaveChanges();
               
     Console.Write(std.StudentID); // 1
 }

EF execute each INSERT command followed by SELECT scope_identity() statement. SCOPE_IDENTITY returns the last identity value inserted into an identity column in the same scope. The above example will execute the following SQL in the database.

info: Microsoft.EntityFrameworkCore.Database.Command[200101]
Executed DbCommand (102ms) [Parameters=[@p0='' (DbType = DateTime2), @p1='
0', @p2='Steve' (Size = 4000), @p3='0'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [Students] ([DateOfBirth], [Height], [StudentName], [Weight])
VALUES (@p0, @p1, @p2, @p3);
SELECT [StudentID], [CreateOrUpdateDate]
FROM [Students]
WHERE @@ROWCOUNT = 1 AND [StudentID] = scope_identity();

The same way, EF also populates the foreign key property. For example, consider the following Student entity that includes a Grade property.

public class Student
{
    public int StudentID { get; set; }
    public string StudentName { get; set; }
    public DateTime? DateOfBirth { get; set; }
    public decimal Height { get; set; }
    public float Weight { get; set; }

    public Grade Grade { get; set; }
}

public class Grade
{
    public int GradeId { get; set; }
    public string GradeName { get; set; }
    public string Section { get; set; }
}

Now, when you add a new Student with a new Grade then EF will populate the Student.Grade.GradeId also.

using (var context = new SchoolContext())
{
    var std = new Student() { StudentName = "Steve", 
                              Grade = new Grade(){  GradeName="1st Grade", Section="C" } };
    context.Students.Add(std);
    context.SaveChanges();

    Console.WriteLine(std.Grade.GradeId);// 1
}

EF will first execute the insert command for a new Grade and then use this new GradeId in the insert command for a Student.

info: Microsoft.EntityFrameworkCore.Database.Command[200101]
Executed DbCommand (94ms) [Parameters=[@p0='1st Grade' (Size = 4000), @p1=
'C' (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [Grades] ([GradeName], [Section])
VALUES (@p0, @p1);
SELECT [GradeId]
FROM [Grades]
WHERE @@ROWCOUNT = 1 AND [GradeId] = scope_identity();
info: Microsoft.EntityFrameworkCore.Database.Command[200101]
Executed DbCommand (7ms) [Parameters=[@p2='' (DbType = DateTime2), @p3='6'
(Nullable = true), @p4='0', @p5='Steve' (Size = 4000), @p6='0'], CommandType='T
ext'
, CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [Students] ([DateOfBirth], [GradeId], [Height], [StudentName],
[Weight])
VALUES (@p2, @p3, @p4, @p5, @p6);
SELECT [StudentID], [CreateOrUpdateDate]
FROM [Students]
WHERE @@ROWCOUNT = 1 AND [StudentID] = scope_identity();