EF Core - Tạo mô hình từ database có sẵn trong EF Core

Tạo mô hình từ database có sẵn trong EF Core

Ở phần này bạn sẽ tìm hiểu cách tạo lớp Context và các lớp thực thể cho cơ sở dữ liệu có sẵn trong Entity Framework Core. Tạo các lớp thực thể và Context cho cơ sở dữ liệu có sẵn được gọi là phương pháp tiếp cận Database First.

EF Core không hỗ trợ trình thiết kế trực quan cho mô hình DB và trình hướng dẫn để tạo các thực thể và các lớp Context tương tự như EF 6.

Vì vậy, chúng ta cần thực hiện kỹ thuật đảo ngược bằng cách sử dụng lệnh Scaffold-DbContext. Lệnh đảo ngược này tạo ra các lớp thực thể và Context (bằng cách kế thừa từ lớp DbContext) dựa trên lược đồ của cơ sở dữ liệu hiện có.

Chúng ta sẽ tạo các lớp thực thể và Context cho cơ sở dữ liệu SchoolDB sau trong MS SQL Server như hình ảnh bên dưới.

Tạo mô hình từ database có sẵn trong EF Core

Lệnh Scaffold-DbContext

Sử dụng lệnh Scaffold-DbContext để tạo một mô hình dựa trên cơ sở dữ liệu hiện tại của bạn. Các tham số sau có thể được chỉ định cho Scaffold-DbContext trong Package Manager Console:

Scaffold-DbContext [-Connection] [-Provider] [-OutputDir] [-Context] [-Schemas>] [-Tables>] 
                   [-DataAnnotations] [-Force] [-Project] [-StartupProject] [<CommonParameters>]

Trong Visual Studio, chọn menu Tools -> NuGet Package Manger -> Package Manger Console và chạy lệnh sau:

PM> Scaffold-DbContext "Server=.\SQLExpress;Database=SchoolDB;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

Trong lệnh trên, tham số đầu tiên là một chuỗi kết nối bao gồm ba phần: Máy chủ DB, tên cơ sở dữ liệu và thông tin bảo mật.

Ở đây, Server=.\SQLExpress; đề cập đến máy chủ cơ sở dữ liệu SQLEXPRESS cục bộ. Database=SchoolDB; chỉ định tên cơ sở dữ liệu "SchoolDB" mà chúng ta sẽ tạo các lớp. Trusted_Connection=True; chỉ định xác thực Windows. Nó sẽ sử dụng thông tin đăng nhập Windows để kết nối với SQL Server.

Tham số thứ hai là tên nhà cung cấp. Chúng tôi sử dụng nhà cung cấp cho SQL Server, vì vậy nó là Microsoft.EntityFrameworkCore.SqlServer.

Tham số -OutputDir mô tả thư mục nơi mà chúng tôi muốn tạo ra tất cả các lớp thực thể, đó là thư mục Models.

Sử dụng lệnh sau để xem chi tiết về lệnh Scaffold-DbContext:

PM> get-help scaffold-dbcontext –detailed

Lệnh trên Scaffold-DbContext tạo các lớp thực thể cho mỗi bảng trong cơ sở dữ liệu SchoolDB và lớp Context với các cấu hình Fluent API cho tất cả các thực thể trong thư mục Models.

Tạo mô hình từ database có sẵn trong EF Core

Sau đây là lớp thực thể Student được tạo cho bảng Student.


using System;
using System.Collections.Generic;

namespace EFCoreTutorials.Models
{
    public partial class Student
    {
        public Student()
        {
            StudentCourse = new HashSet<StudentCourse>();
        }

        public int StudentId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int? StandardId { get; set; }

        public Standard Standard { get; set; }
        public StudentAddress StudentAddress { get; set; }
        public ICollection<StudentCourse> StudentCourse { get; set; }
    }
}

Sau đây là lớp SchoolDBContext mà bạn có thể sử dụng để lưu hoặc truy xuất dữ liệu.


using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

namespace EFCoreTutorials.Models
{
    public partial class SchoolDBContext : DbContext
    {
        public virtual DbSet<Course> Course { get; set; }
        public virtual DbSet<Standard> Standard { get; set; }
        public virtual DbSet<Student> Student { get; set; }
        public virtual DbSet<StudentAddress> StudentAddress { get; set; }
        public virtual DbSet<StudentCourse> StudentCourse { get; set; }
        public virtual DbSet<Teacher> Teacher { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
                optionsBuilder.UseSqlServer(@"Server=.\SQLExpress;Database=SchoolDB;Trusted_Connection=True;");
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Course>(entity =>
            {
                entity.Property(e => e.CourseName)
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.HasOne(d => d.Teacher)
                    .WithMany(p => p.Course)
                    .HasForeignKey(d => d.TeacherId)
                    .OnDelete(DeleteBehavior.Cascade)
                    .HasConstraintName("FK_Course_Teacher");
            });

            modelBuilder.Entity<Standard>(entity =>
            {
                entity.Property(e => e.Description)
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.Property(e => e.StandardName)
                    .HasMaxLength(50)
                    .IsUnicode(false);
            });

            modelBuilder.Entity<Student>(entity =>
            {
                entity.Property(e => e.StudentId).HasColumnName("StudentID");

                entity.Property(e => e.FirstName)
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.Property(e => e.LastName)
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.HasOne(d => d.Standard)
                    .WithMany(p => p.Student)
                    .HasForeignKey(d => d.StandardId)
                    .OnDelete(DeleteBehavior.Cascade)
                    .HasConstraintName("FK_Student_Standard");
            });

            modelBuilder.Entity<StudentAddress>(entity =>
            {
                entity.HasKey(e => e.StudentId);

                entity.Property(e => e.StudentId)
                    .HasColumnName("StudentID")
                    .ValueGeneratedNever();

                entity.Property(e => e.Address1)
                    .IsRequired()
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.Property(e => e.Address2)
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.Property(e => e.City)
                    .IsRequired()
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.Property(e => e.State)
                    .IsRequired()
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.HasOne(d => d.Student)
                    .WithOne(p => p.StudentAddress)
                    .HasForeignKey<StudentAddress>(d => d.StudentId)
                    .HasConstraintName("FK_StudentAddress_Student");
            });

            modelBuilder.Entity<StudentCourse>(entity =>
            {
                entity.HasKey(e => new { e.StudentId, e.CourseId });

                entity.HasOne(d => d.Course)
                    .WithMany(p => p.StudentCourse)
                    .HasForeignKey(d => d.CourseId)
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_StudentCourse_Course");

                entity.HasOne(d => d.Student)
                    .WithMany(p => p.StudentCourse)
                    .HasForeignKey(d => d.StudentId)
                    .HasConstraintName("FK_StudentCourse_Student");
            });

            modelBuilder.Entity<Teacher>(entity =>
            {
                entity.Property(e => e.StandardId).HasDefaultValueSql("((0))");

                entity.Property(e => e.TeacherName)
                    .HasMaxLength(50)
                    .IsUnicode(false);

                entity.HasOne(d => d.Standard)
                    .WithMany(p => p.Teacher)
                    .HasForeignKey(d => d.StandardId)
                    .OnDelete(DeleteBehavior.Cascade)
                    .HasConstraintName("FK_Teacher_Standard");
            });
        }
    }
}

 

Lưu ý: EF Core chỉ tạo các lớp thực thể cho các bảng chứ không tạo cho Stored Procedure hoặc View.

DotNet CLI

Nếu bạn sử dụng giao diện dòng lệnh dotnet để thực thi các lệnh EF Core thì hãy mở dấu nhắc lệnh và điều hướng đến thư mục gốc của dự án và thực hiện lệnh dotnet ef dbcontext scaffold sau:

> dotnet ef dbcontext scaffold "Server=.\SQLEXPRESS;Database=SchoolDB;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -o Models

Như vậy là bạn có thể tạo mô hình EF Core cho cơ sở dữ liệu có sẵn.

Lưu ý: Khi bạn đã tạo mô hình, bạn phải sử dụng các lệnh chuyển đổi (migration) bất cứ lúc nào bạn thay đổi mô hình để giữ cho cơ sở dữ liệu được cập nhật với mô hình.