EF 6 - Lưu dữ liệu bị ngắt kết nối

Lưu dữ liệu trong kịch bản bị ngắt kết nối

Lưu dữ liệu trong kịch bản bị ngắt kết nối hơi khác một chút so với kịch bản được kết nối.

Trong kịch bản bị ngắt kết nối, một thể thể của DbContext không biết về các thực thể bị ngắt kết nối vì các thực thể được tạo hoặc sửa đổi ngoài phạm vi của DbContext thể hiện hiện tại.

Vì vậy, bạn cần phải đính kèm các thực thể bị ngắt kết nối với một Context với trạng thái EntityState phù hợp để thực hiện các thao tác INSERT hoặc UPDATE trong cơ sở dữ liệu.

Trong kịch bản bị ngắt kết nối, bạn cần tìm hiểu xem một thực thể là thêm mới hay hiện có và dựa vào đó bạn có thể thiết lập trạng thái EntityState.

Ở đây, nếu giá trị thuộc tính khóa bằng 0 thì chúng tôi sẽ coi đó là một thực thể mới và vì vậy chúng tôi sẽ thiết lập trạng thái là Added.

Nếu giá trị thuộc tính khóa lớn hơn 0, thì có nghĩa là nó là một thực thể hiện có và vì vậy chúng tôi sẽ đặt trạng thái là Modified.

 

Lưu dữ liệu trong kịch bản bị ngắt kết nối

Ưu điểm:

  • Sử dụng ít tài nguyên hơn so với kịch bản được kết nối.
  • Không mở kết nối với cơ sở dữ liệu.

Nhược điểm:

  • Cần đặt trạng thái thích hợp cho từng thực thể trước khi lưu.
  • Thực hiện chậm hơn so với kịch bản được kết nối.

Thêm mới dữ liệu trong kịch bản bị ngắt kết nối

Ví dụ sau đây cho thấy việc lưu một thực thể bị ngắt kết nối.

// disconnected new entity 
var student = new Student()
{ 
    StudentName = "Bill" 
};

using (var context = new SchoolDBEntities())
{
    context.Entry(student).State = student.StudentId == 0 ? EntityState.Added : EntityState.Modified;

    context.SaveChanges();
}

Trong ví dụ trên, student là một đối tượng thực thể bị ngắt kết nối và context không biết được trạng thái của nó.

Đoạn mã context.Entry(student).State = student.StudentId == 0 ? EntityState.Added : EntityState.Modified; sẽ thiết lập trạng thái Added nếu giá trị của thuộc tính khóa StudentId bằng 0, ngược lại nó sẽ thiết lập trạng thái là Modified. Phương thức SaveChanges() sẽ tạo và thực hiện lệnh INSERT sau vào cơ sở dữ liệu.

exec sp_executesql N'INSERT [dbo].[Student]([StudentName], [StandardId])
VALUES (@0, NULL)
SELECT [StudentID] FROM [dbo].[Student]
WHERE @@ROWCOUNT > 0 AND [StudentID] = scope_identity(),@0='Bill'

Cập nhật dữ liệu trong kịch bản bị ngắt kết nối

Tương tự, nếu giá trị của StudentId khác 0, thì nó sẽ thiết lập trạng thái EntityStateModified và do đó khi gọi phương thức SaveChanges() sẽ thực thi lệnh UPDATE.

// disconnected existing entity 
var student = new Student()
{
    StudentId = 1,
    StudentName = "Steve" 
};

using (var context = new SchoolDBEntities())
{
    context.Entry(student).State = student.StudentId == 0 ? EntityState.Added : EntityState.Modified;

    context.SaveChanges();
}

Trong ví dụ trên, một đối tượng của thực thể Student có thuộc tính khóa StudentId lớn hơn 0, vì vậy nó sẽ được đánh dấu là Modified. Điều này sẽ thực hiện lệnh UPDATE sau trong cơ sở dữ liệu.

exec sp_executesql N'UPDATE [dbo].[Student]
SET [StudentName] = @0
WHERE @@ROWCOUNT > 0 AND [StudentID] = @1'N'@0 varchar(50),@1 int',@0='Steve',@1=1

Xóa dữ liệu trong kịch bản bị ngắt kết nối

Xóa một thực thể bị ngắt kết nối rất dễ dàng. Chỉ cần đặt trạng thái thành Deleted bằng phương thức Entry() như ví dụ dưới đây.

// disconnected entity to be deleted
var student = new Student()
{ 
    StudentId = 1 
};

using (var context = new SchoolDBEntities())
{
    context.Entry(student).State = System.Data.Entity.EntityState.Deleted;    

    context.SaveChanges();
}  

Trong ví dụ trên, một thể hiện của thực thể Student chỉ chứa thuộc tính khóa StudentId. Để xóa một thực thể, nó chỉ yêu cầu một thuộc tính khóa. Câu lệnh context.Entry(student).State = System.Data.Entity.EntityState.Deleted sẽ gắn một thực thể vào một Context và gán trạng thái của nó thành Deleted. Điều này sẽ thực hiện lệnh DELETE sau trong cơ sở dữ liệu.

exec sp_executesql N'DELETE [dbo].[Students]
WHERE ([StudentId] = @0)',N'@0 int',@0=1
Go