在这里,您将学习如何在Entity Framework Core中为现有数据库创建上下文和实体类。为现有数据库创建实体和上下文类称为Database-First方法。
EF Core不支持用于可视化设计器的DB模型和向导来创建类似于EF 6的实体和上下文类。因此,我们需要使用Scaffold-DbContext命令进行逆向工程。此逆向工程命令基于现有数据库的架构创建实体和上下文类(通过派生DbContext)。
让我们在下面显示的本地MS SQL Server中为以下SchoolDB数据库创建实体和上下文类。
使用Scaffold-DbContext基于现有数据库创建模型。可以在Package Manager控制台中的Scaffold-DbContext中指定以下参数:
Scaffold-DbContext [-Connection] [-Provider] [-OutputDir] [-Context] [-Schemas>] [-Tables>]
[-DataAnnotations] [-Force] [-Project] [-StartupProject] [<CommonParameters>]
在Visual Studio中,选择菜单工具-> NuGet软件包管理器->软件包管理器控制台,然后运行以下命令:
Scaffold-DbContext "Server=.\SQLExpress;Database=SchoolDB;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
在上面的命令中,第一个参数是一个连接字符串,它包括三个部分:
数据库服务器, 数据库名称和安全信息。在这里,Server=.\SQLExpress;指本地SQLEXPRESS数据库服务器。
Database=SchoolDB; 指定我们要为其创建类的数据库名称“ SchoolDB”。 Trusted_Connection=True; 指定Windows身份验证。
它将使用Windows凭据连接到SQL Server。第二个参数是提供程序名称。我们将提供程序用于SQL Server,因此它是Microsoft.EntityFrameworkCore.SqlServer。 -OutputDir参数指定我们要在其中生成所有类的目录,在本例中为Models文件夹。
使用以下命令可获得有关Scaffold-DbContext命令的详细帮助:
get-help scaffold-dbcontext –detailed
上面的Scaffold-DbContext命令使用为Models文件夹中所有实体的Fluent API配置为SchoolDB数据库中的每个表创建实体类,并通过派生DbContext创建数据库上下文类。
以下是为Student表生成的Student实体类。:
using System;
using System.Collections.Generic;
namespace EFCoreTutorials.Models
{
public partial class Student
{
public Student()
{
StudentCourse = new HashSet();
}
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 { get; set; }
}
}
以下是SchoolDBContext类,可用于保存或检索数据:
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
namespace EFCoreTutorials.Models
{
public partial class SchoolDBContext : DbContext
{
public virtual DbSet Course { get; set; }
public virtual DbSet Standard { get; set; }
public virtual DbSet Student { get; set; }
public virtual DbSet StudentAddress { get; set; }
public virtual DbSet StudentCourse { get; set; }
public virtual DbSet 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(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(entity =>
{
entity.Property(e => e.Description)
.HasMaxLength(50)
.IsUnicode(false);
entity.Property(e => e.StandardName)
.HasMaxLength(50)
.IsUnicode(false);
});
modelBuilder.Entity(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(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(d => d.StudentId)
.HasConstraintName("FK_StudentAddress_Student");
});
modelBuilder.Entity(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(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");
});
}
}
}
注意:EF Core仅为表创建实体类,而不为StoredProcedures或View创建实体类。
如果使用dotnet命令行界面执行EF Core命令,则打开命令提示符并导航到根文件夹,然后执行以下dotnet ef dbcontext scaffold命令:
通过本文学习,您可以使用EF Core为现有数据库创建EF Core模型。
注意:创建模型后,无论何时更改模型,都必须使用“迁移”命令,以使数据库与模型保持最新。