DbContext và DbSet trong Entity Framework

DbContext trong Entity Framework

Như bạn đã xem trong phần Tạo mô hình dữ liệu thực thể trước đó, EDM có lớp SchoolDBEntities được dẫn xuất từ lớp System.Data.Entity.DbContext được trình bày ở hình bên dưới. Lớp dẫn xuất DbContext được gọi là lớp Context trong Entity Framework.

Lớp DbContext trong Entity Framework

DbContext là một lớp quan trọng trong Entity Framework API. Nó là cầu nối giữa các lớp thực thể và cơ sở dữ liệu.

Lớp DbContext trong Entity Framework

DbContext là lớp chính chịu trách nhiệm tương tác với cơ sở dữ liệu. Nó chịu trách nhiệm cho các hoạt động sau:

  • Truy vấn: Chuyển đổi các truy vấn LINQ-to-Entities thành truy vấn SQL và gửi chúng đến cơ sở dữ liệu.
  • Theo dõi thay đổi: Theo dõi các thay đổi xảy ra trên các thực thể sau khi truy vấn từ cơ sở dữ liệu.
  • Dữ liệu bền vững: Thực hiện các thao tác insert, updatedelete vào cơ sở dữ liệu, dựa trên các trạng thái của thực thể.
  • Bộ nhớ đệm: Cung cấp bộ nhớ đệm cấp đầu tiên theo mặc định. Nó lưu trữ các thực thể đã được truy xuất trong suốt thời gian tồn tại của một lớp Context.
  • Quản lý mối quan hệ: Quản lý các mối quan hệ bằng cách sử dụng CSDL, MSL và SSDL trong cách tiếp cận Database First hoặc Model First và sử dụng các cấu hình Fluent API trong cách tiếp cận Code First.
  • Ánh xạ đối tượng: Chuyển đổi dữ liệu thô từ cơ sở dữ liệu thành các đối tượng thực thể.

Sau đây là một ví dụ về lớp SchoolDBEntities (lớp Context dẫn xuất từ lớp DbContext) được tạo bằng EDM cho cơ sở dữ liệu SchoolDB trong phần trước.

namespace ComdyTechnical
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using System.Data.Entity.Core.Objects;
    using System.Linq;
    
    public partial class SchoolDBEntities : DbContext
    {
        public SchoolDBEntities()
            : base("name=SchoolDBEntities")
        {
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }
    
        public virtual DbSet<Course> Courses { get; set; }
        public virtual DbSet<Standard> Standards { get; set; }
        public virtual DbSet<Student> Students { get; set; }
        public virtual DbSet<StudentAddress> StudentAddresses { get; set; }
        public virtual DbSet<Teacher> Teachers { get; set; }
        public virtual DbSet<View_StudentCourse> View_StudentCourse { get; set; }
    
        public virtual ObjectResult<GetCoursesByStudentId_Result> GetCoursesByStudentId(Nullable<int> studentId)
        {
            var studentIdParameter = studentId.HasValue ?
                new ObjectParameter("StudentId", studentId) :
                new ObjectParameter("StudentId", typeof(int));
    
            return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<GetCoursesByStudentId_Result>("GetCoursesByStudentId", studentIdParameter);
        }
    
        public virtual int sp_DeleteStudent(Nullable<int> studentId)
        {
            var studentIdParameter = studentId.HasValue ?
                new ObjectParameter("StudentId", studentId) :
                new ObjectParameter("StudentId", typeof(int));
    
            return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("sp_DeleteStudent", studentIdParameter);
        }
    
        public virtual ObjectResult<Nullable<decimal>> sp_InsertStudentInfo(Nullable<int> standardId, string studentName)
        {
            var standardIdParameter = standardId.HasValue ?
                new ObjectParameter("StandardId", standardId) :
                new ("StandardId", typeof(int));
    
            var studentNameParameter = studentName != null ?
                new ObjectParameter("StudentName", studentName) :
                new ObjectParameter("StudentName", typeof(string));
    
            return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<Nullable<decimal>>("sp_InsertStudentInfo", standardIdParameter, studentNameParameter);
        }
    
        public virtual int sp_UpdateStudent(Nullable<int> studentId, Nullable<int> standardId, string studentName)
        {
            var studentIdParameter = studentId.HasValue ?
                new ObjectParameter("StudentId", studentId) :
                new ObjectParameter("StudentId", typeof(int));
    
            var standardIdParameter = standardId.HasValue ?
                new ObjectParameter("StandardId", standardId) :
                new ObjectParameter("StandardId", typeof(int));
    
            var studentNameParameter = studentName != null ?
                new ObjectParameter("StudentName", studentName) :
                new ObjectParameter("StudentName", typeof(string));
    
            return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("sp_UpdateStudent", studentIdParameter, standardIdParameter, studentNameParameter);
        }
    }
}        

Như bạn có thể thấy trong ví dụ trên, lớp Context SchoolDBEntities có một tập kiểu thực thể DbSet<TEntity> cho tất cả các thực thể. Nó cũng có các chức năng cho stored procedures và views có trong EDM.

Phương thức OnModelCreating cho phép chúng ta cấu hình các mô hình sử dụng DbModelBuilder Fluent API trong Entity Framework 6.

Phương thức của DbContext

Phương thức Mô tả
Entry Trả về một DbEntityEntry cho một thực thể. Phương thức này cung cấp truy cập để thay đổi thông tin theo dõi và hoạt động cho thực thể.
SaveChanges Thực thi các lệnh INSERT, UPDATE và DELETE vào cơ sở dữ liệu cho các thực thể với trạng thái Added, Modified và Deleted.
SaveChangesAsync Phương thức SaveChanges() không đồng bộ
Set Tạo một DbSet<TEntity> được sử dụng để truy vấn và lưu các thể hiện của TEntity.
OnModelCreating Ghi đè phương thức này để bổ sung cấu hình cho mô hình thực thể.

Thuộc tính của DbContext

Thuộc tính Mô tả
ChangeTracker Cung cấp truy cập vào thông tin và hoạt động cho các trường hợp thực thể mà Context này đang theo dõi.
Configuration Cung cấp truy cập vào các tùy chọn cấu hình.
Database Cung cấp truy cập vào cơ sở dữ liệu thông tin và hoạt động.

DbSet trong Entity Framework

Lớp DbSet đại diện cho một tập thực thể có thể được sử dụng để thực hiện các thao tác tạo, đọc, cập nhật, và xóa (CRUD - create, read, update, delete).

Lớp Context (dẫn xuất từ lớp DbContext) phải có các thuộc tính kiểu DbSet cho các thực thể ánh xạ tới các table và view trong cơ sở dữ liệu.

DbSet trong Entity Framework

Bảng sau liệt kê các phương thức quan trọng của lớp DbSet:

Phương thức Mô tả
Add

Thêm thực thể đã cho vào Context với trạng thái Added. Khi các thay đổi được lưu, các thực thể trong trạng thái Added sẽ được thêm vào cơ sở dữ liệu. Sau khi các thay đổi được lưu, trạng thái đối tượng thay đổi thành Unchanged.

Ví dụ: dbcontext.Students.Add(studentEntity)

AsNoTracking <Entity> Trả về một truy vấn mới trong đó các thực thể được trả về sẽ không được lưu trong bộ nhớ cache trong DbContext. (Kế thừa từ DbQuery.)

Các thực thể được trả về là AsNoTracking sẽ không được DBContext theo dõi. Đây sẽ là một sự tăng hiệu suất đáng kể cho các thực thể chỉ đọc.

Ví dụ: var studentList = dbcontext.Students.AsNoTracking<Student>().ToList<Student>();

Attach(Entity) Đính kèm thực thể đã cho vào ngữ cảnh ở trạng thái Unchanged

Ví dụ: dbcontext.Students.Attach(studentEntity);

Create Tạo một thể hiện mới của một thực thể. Thể hiện này không được thêm hoặc đính kèm vào tập hợp. Thể hiện được trả về sẽ là một proxy nếu Context được cấu hình để tạo proxy và kiểu thực thể đáp ứng các yêu cầu để tạo proxy.

Ví dụ: var newStudentEntity = dbcontext.Students.Create();

Find(int) Sử dụng giá trị khóa chính để tìm một thực thể được theo dõi bởi Context. Nếu thực thể không có trong Context, thì một truy vấn sẽ được thực thi và đánh giá dựa trên dữ liệu trong nguồn dữ liệu và null được trả về nếu không tìm thấy thực thể trong ngữ cảnh hoặc trong nguồn dữ liệu. Lưu ý rằng phương thức Find cũng trả về các thực thể đã được thêm vào Context nhưng chưa được lưu vào cơ sở dữ liệu.

Ví dụ: var student = dbcontext.Students.Find(1);

Include Trả về kèm theo truy vấn non-generic LINQ-to-Entities (Kế thừa từ DbQuery)

Ví dụ: var studentList = dbcontext.Students.Incoide("StudentAddress").ToList <Student>(); var studentList = dbcontext.Students.Incoide(s => s.StudentAddress).ToList<Student>();

Remove Đánh dấu thực thể đã cho là Removed. Khi các thay đổi được lưu, thực thể sẽ bị xóa khỏi cơ sở dữ liệu. Thực thể phải tồn tại trong Context ở một số trạng thái khác trước khi phương thức này được gọi.

Ví dụ: dbcontext.Students.Remove(studentEntity);

SqlQuery Tạo một truy vấn SQL thô sẽ trả về các thực thể. Theo mặc định, các thực thể được trả về được theo dõi bởi Context; điều này có thể được thay đổi bằng cách gọi AsNoTracking trên DbSqlQuery<TEntity> được trả về từ phương thức này.

Ví dụ: var studentEntity = dbcontext.Students.SqlQuery("select top 1 * from student where studentid = 1").FirstOrDefault<Student>();

Truy cập MSND để biết thêm thông tin về DbSet .

Entity Framework
Bài Viết Liên Quan:
2 kịch bản lưu dữ liệu trong Entity Framework Core
Trung Nguyen 30/04/2020
2 kịch bản lưu dữ liệu trong Entity Framework Core

2 kịch bản lưu dữ liệu trong Entity Framework Core là kịch bản được kết nối và kịch bản ngắt kết nối.

Ứng dụng Entity Framework Core đầu tiên
Trung Nguyen 29/04/2020
Ứng dụng Entity Framework Core đầu tiên

Tạo ứng dụng .NET Core Console đầu tiên và cấu hình sử dụng Entity Framework Core.

Truy vấn trong Entity Framework Core
Trung Nguyen 29/04/2020
Truy vấn trong Entity Framework Core

Truy vấn trong Entity Framework Core có gì mới? Truy vấn trong EF Core khác EF ở những điểm nào.

Entity Framework Core toàn tập
Trung Nguyen 29/04/2020
Entity Framework Core toàn tập

Entity Framework Core toàn tập sẽ hướng dẫn bạn tất cả mọi thứ về Entity Framework Core.