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