EF 6 - Attach entity ngắt kết nối
Attach entity bị ngắt kết nối trong Entity Framework
Ở bài viết này bạn sẽ tìm hiểu về các phương thức khác nhau trong Entity Framework 6.x để gắn các biểu đồ thực thể bị ngắt kết nối vào một Context.
Lưu một thực thể trong kịch bản bị ngắt kết nối khác với kịch bản được kết nối. Có hai điều chúng ta cần làm khi nhận được biểu đồ thực thể bị ngắt kết nối hoặc thậm chí là một thực thể bị ngắt kết nối.
- Đầu tiên, chúng ta cần đính kèm các thực thể với thể hiện của Context mới và làm cho Context biết về các thực thể này.
- Thứ hai, thiết lập trạng thái
EntityState
phù hợp cho từng thực thể theo cách thủ công vì thể hiện của Context không biết gì về các thao tác được thực hiện trên các thực thể bị ngắt kết nối, do đó nó không thể tự động áp dụng trạng thái thích hợp choEntityState
.
Hình dưới đây minh họa quá trình này.
Entity Framework cung cấp các phương thức sau để gắn các thực thể bị ngắt kết nối vào một Context và gán các trạng thái EntityState
cho từng thực thể trong biểu đồ thực thể.
- DbContext.Entry()
- DbSet.Add()
- DbSet.Attach()
Phương thức DbContext.Entry()
Phương thức Entry()
của lớp DbContext
trả về một thể hiện của DbEntityEntry
cho thực thể được chỉ định.
Đối tượng DbEntityEntry
cung cấp nhiều thông tin khác nhau về thực thể được chỉ định và khả năng thực hiện một hành động trên thực thể.
Quan trọng nhất, chúng ta có thể thay đổi trạng thái EntityState
của thực thể được chỉ định bằng cách sử dụng thuộc tính State
được trình bày ở bên dưới.
context.Entry(entity).state = EntityState.Added/Modified/Deleted
Phương thức Entry
gắn toàn bộ biểu đồ thực thể đến một Context với trạng thái được chỉ định cho một thực thể cha và tất cả thực thể con của nó. Hãy xem ví dụ sau.
var student = new Student() { //Root entity (empty key)
StudentName = "Bill",
StandardId = 1,
Standard = new Standard() //Child entity (with key value)
{
StandardId = 1,
StandardName = "Grade 1"
},
Courses = new List<Course>() {
new Course(){ CourseName = "Machine Language" }, //Child entity (empty key)
new Course(){ CourseId = 2 } //Child entity (with key value)
}
};
using (var context = new SchoolDBEntities())
{
context.Entry(student).State = EntityState.Added;
foreach (var entity in context.ChangeTracker.Entries()){
Console.WriteLine("{0}: {1}", entity.Entity.GetType().Name, entity.State);
}
}
Kết quả khi biên dịch và chạy chương trình:
Student: Added
Standard: Added
Course: Added
Course: Added
Trong ví dụ trên, biểu đồ thực thể của Student
bao gồm các thực thể Standard
và Course
. Câu lệnh context.Entry(student).State = EntityState.Added;
gán trạng thái Added
cho thực thể cha cũng như cho tất cả các thực thể con bất kể thực thể con có chứa giá trị thuộc tính khóa trống hay không. Vì vậy, nên sử dụng phương thức Entry()
một cách cẩn thận.
Bảng sau liệt kê hành vi của phương thức Entry()
.
Trạng thái thực thể cha | Trạng thái của các thực thể con |
---|---|
Added | Added |
Modified | Unchanged |
Deleted | Tất cả thực thể con sẽ là null |
Phương thức DbSet.Add()
Phương thức DbSet.Add()
gắn toàn bộ biểu đồ thực thể đến một Context và tự động áp dụng trạng thái Added
cho tất cả các thực thể.
//disconnected entity graph
Student disconnectedStudent = new Student()
{
StudentName = "New Student"
};
disconnectedStudent.StudentAddress = new StudentAddress()
{
Address1 = "Address",
City = "City1"
};
using (var context = new SchoolDBEntities())
{
context.Students.Add(disconnectedStudent);
// get DbEntityEntry instance to check the EntityState of specified entity
var studentEntry = context.Entry(disconnectedStudent);
var addressEntry = context.Entry(disconnectedStudent.StudentAddress);
Console.WriteLine("Student: {0}", studentEntry.State);
Console.WriteLine("StudentAddress: {0}", addressEntry.State);
}
Kết quả khi biên dịch và chạy chương trình:
Student: Added
StudentAddress: Added
Phương thức DbSet.Add()
gắn toàn bộ biểu đồ thực thể đến một Context với trạng thái Added
cho từng đối tượng. Việc gọi phương thức context.Savechanges()
sẽ thực thi lệnh INSERT cho tất cả các thực thể trong cơ sở dữ liệu.
Phương thức DbSet.Attach()
Phương thức DbSet.Attach()
gắn toàn bộ biểu đồ thực thể đến một Context với trạng thái thực thể Unchanged
.
//disconnected entity graph
Student disconnectedStudent = new Student()
{
StudentName = "New Student"
};
disconnectedStudent.StudentAddress = new StudentAddress()
{
Address1 = "Address",
City = "City1"
};
using (var context = new SchoolDBEntities())
{
context.Students.Attach(disconnectedStudent);
// get DbEntityEntry instance to check the EntityState of specified entity
var studentEntry = context.Entry(disconnectedStudent);
var addressEntry = context.Entry(disconnectedStudent.StudentAddress);
Console.WriteLine("Student: {0}", studentEntry.State);
Console.WriteLine("StudentAddress: {0}", addressEntry.State);
}
Kết quả khi biên dịch và chạy chương trình:
Student: Unchanged
StudentAddress: Unchanged
Lớp DbEntityEntry
Lớp DbEntityEntry
là một lớp quan trọng, hữu ích trong việc truy xuất các thông tin khác nhau về một thực thể. Bạn có thể lấy một thể hiện của DBEntityEntry của một thực thể cụ thể bằng cách sử dụng phương thức Entry
của DbContext. Ví dụ:
DbEntityEntry studentEntry = dbcontext.Entry(entity);
Lớp DbEntityEntry
cho phép bạn truy cập trạng thái của thực thể và các giá trị hiện tại và ban đầu của tất cả các thuộc tính của một thực thể nhất định.
Đoạn mã ví dụ sau đây cho thấy cách truy xuất thông tin quan trọng của một thực thể cụ thể.
using (var dbCtx = new SchoolDBEntities())
{
//get student whose StudentId is 1
var student = dbCtx.Students.Find(1);
//edit student name
student.StudentName = "Edited name";
//get DbEntityEntry object for student entity object
var entry = dbCtx.Entry(student);
//get entity information e.g. full name
Console.WriteLine("Entity Name: {0}", entry.Entity.GetType().FullName);
//get current EntityState
Console.WriteLine("Entity State: {0}", entry.State );
Console.WriteLine("********Property Values********");
foreach (var propertyName in entry.CurrentValues.PropertyNames )
{
Console.WriteLine("Property Name: {0}", propertyName);
//get original value
var orgVal = entry.OriginalValues[propertyName];
Console.WriteLine(" Original Value: {0}", orgVal);
//get current values
var curVal = entry.CurrentValues[propertyName];
Console.WriteLine(" Current Value: {0}", curVal);
}
}
Đây là kết quả khi biên dịch và thực thi:
Entity Name: Student
Entity State: Modified
********Property Values********
Property Name: StudentID
Original Value: 1
Current Value: 1
Property Name: StudentName
Original Value: First Student Name
Current Value: Edited name
Property Name: StandardId
Original Value:
Current Value:
Lớp DbEntityEntry
cho phép bạn thiết lập trạng thái của EntityState
như ví dụ bên dưới.
context.Entry(student).State = System.Data.Entity.EntityState.Modified;
Truy cập MSDN để biết thêm thông tin về lớp DbEntityEntry.