VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > c#编程 >
  • EF Core基础映射——C#编写实体与表关联

第一部分:C#基础入门
EF Core基础映射——实体与表关联
实例介绍
EF Core(Entity Framework Core)是.NET生态中最流行的ORM框架(对象关系映射),它能将C#实体类与数据库表无缝关联,让开发者用面向对象的方式操作数据库,无需手写复杂SQL。实体与表的关联是EF Core的核心能力,包括类→表、属性→列、主键/外键配置、导航属性关联等关键环节。
本节通过“学生选课系统”场景,带你掌握EF Core实体与表关联的核心配置:数据vb.net教程C#教程python教程SQL教程access 2010教程注解、Fluent API、导航属性(一对多/多对多),让你快速上手EF Core的基础映射。
需求分析
设计一个学生选课系统的实体映射方案,核心需求:
1.实体→表映射:将Student类映射到Students表,Course类映射到Courses表;
2.属性→列映射:指定列名、数据类型、长度(如Student.Name映射到StudentName列,类型为nvarchar(100));
3.主键配置:设置Student.Id和Course.Id为主键;
4.关联配置:实现学生与课程的多对多关联(一个学生可选多门课,一门课可被多个学生选);
5.导航属性:通过导航属性Student.Courses和Course.Students查询关联数据;
6.测试验证:添加数据并查询关联关系,验证映射正确性。
代码实现
前置条件:
安装EF Core包:Microsoft.EntityFrameworkCore、Microsoft.EntityFrameworkCore.SqlServer;
创建数据库SchoolDB(或复用之前的数据库);

  1. 实体类定义(数据注解配置)
    csharp
	using System.Collections.Generic;
	using System.ComponentModel.DataAnnotations;
	using System.ComponentModel.DataAnnotations.Schema;
	
	// 学生实体:映射到Students表
	[Table("Students")] // 指定表名(若类名与表名一致可省略)
	public class Student {
	[Key] // 主键注解
	public int Id { get; set; }
	
	[Column("StudentName", TypeName = "nvarchar(100)")] // 列名+类型
	[Required] // 非空约束
	public string Name { get; set; }
	
	public int Age { get; set; }
	
	// 导航属性:学生选的课程(多对多)
	public ICollection<StudentCourse> StudentCourses { get; set; } = new List<StudentCourse>();
	}
	
	// 课程实体:映射到Courses表
	[Table("Courses")]
	public class Course {
	[Key]
	public int Id { get; set; }
	
	[Column("CourseName", TypeName = "nvarchar(50)")]
	[Required]
	public string Name { get; set; }
	
	public int Credits { get; set; }
	
	// 导航属性:选这门课的学生(多对多)
	public ICollection<StudentCourse> StudentCourses { get; set; } = new List<StudentCourse>();
	}
	
	// 中间实体:学生-课程关联表(EF Core 3.x需显式定义,5+可省略)
	[Table("StudentCourses")]
	public class StudentCourse {
	[Key]
	public int Id { get; set; }
	
	[ForeignKey("Student")] // 外键:关联Student表的Id
	public int StudentId { get; set; }
	
	[ForeignKey("Course")] // 外键:关联Course表的Id
	public int CourseId { get; set; }
	
	// 引用导航属性:关联的学生和课程
	public Student Student { get; set; }
	public Course Course { get; set; }
	}
  1. DbContext配置(Fluent API增强映射)
    csharp
	using Microsoft.EntityFrameworkCore;
	
	public class SchoolDbContext : DbContext {
	// 数据库连接字符串
	private const string ConnStr = @"Data Source=(localdb)MSSQLLocalDB;Initial Catalog=SchoolDB;Integrated Security=True;";
	
	// DbSet:对应数据库表
	public DbSet<Student> Students { get; set; }
	public DbSet<Course> Courses { get; set; }
	public DbSet<StudentCourse> StudentCourses { get; set; }
	
	// 配置数据库连接
	protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
	optionsBuilder.UseSqlServer(ConnStr);
	}
	
	// Fluent API:更灵活的映射配置(优先级高于数据注解)
	protected override void OnModelCreating(ModelBuilder modelBuilder) {
	// 配置Student实体
	modelBuilder.Entity<Student>()
	.ToTable("Students") // 确认表名
	.Property(s => s.Name)
	.HasMaxLength(100) // 最大长度
	.IsRequired(); // 非空
	
	// 配置Course实体
	modelBuilder.Entity<Course>()
	.ToTable("Courses")
	.Property(c => c.Name)
	.HasMaxLength(50)
	.IsRequired();
	
	// 配置StudentCourse中间表(多对多关联)
	modelBuilder.Entity<StudentCourse>()
	.HasKey(sc => sc.Id); // 复合主键可选:sc => new { sc.StudentId, sc.CourseId }
	
	// 多对多关联:Student ↔ Course
	modelBuilder.Entity<StudentCourse>()
	.HasOne(sc => sc.Student) // StudentCourse属于一个Student
	.WithMany(s => s.StudentCourses) // Student有多个StudentCourse
	.HasForeignKey(sc => sc.StudentId); // 外键StudentId
	
	modelBuilder.Entity<StudentCourse>()
	.HasOne(sc => sc.Course) // StudentCourse属于一个Course
	.WithMany(c => c.StudentCourses) // Course有多个StudentCourse
	.HasForeignKey(sc => sc.CourseId); // 外键CourseId
	}
	}
  1. 测试代码(验证关联关系)
    csharp
	class Program {
	static void Main() {
	using (var db = new SchoolDbContext()) {
	// 1. 添加测试数据
	var math = new Course { Name = "高等数学", Credits = 4 };
	var english = new Course { Name = "大学英语", Credits = 3 };
	var student = new Student { Name = "张三", Age = 20 };
	
	// 关联学生和课程
	student.StudentCourses.Add(new StudentCourse { Course = math });
	student.StudentCourses.Add(new StudentCourse { Course = english });
	
	db.Students.Add(student);
	db.SaveChanges(); // 保存到数据库
	
	// 2. 查询关联数据:获取张三选的课程
	var zhangSan = db.Students.First(s => s.Name == "张三");
	Console.WriteLine($"张三选的课程:");
	foreach (var sc in zhangSan.StudentCourses) {
	Console.WriteLine($"- {sc.Course.Name}({sc.Course.Credits}学分)");
	}
	}
	}
	}

逐行讲解

  1. 实体类注解配置
    [Table("Students")]:将Student类映射到数据库Students表,若类名与表名一致可省略;
    [Key]:标记属性为主键,EF Core默认识别Id或类名+Id(如StudentId)作为主键;
    [Column("StudentName", TypeName = "nvarchar(100)")]:指定属性映射到StudentName列,类型为nvarchar(100);
    [ForeignKey("Student")]:标记StudentId为外键,关联Student实体;
    导航属性:StudentCourses是集合导航属性,代表学生关联的课程记录;
  2. Fluent API配置
    OnModelCreating:EF Core的核心配置方法,用Fluent API实现复杂映射(优先级高于数据注解);
    HasOne/WithMany:配置一对多关联,HasOne表示“属于一个”,WithMany表示“有多个”;
    HasForeignKey:指定外键列,明确关联关系;
    HasMaxLength/IsRequired:补充列约束(长度、非空),与数据注解功能一致但更灵活;
  3. 测试代码逻辑
    添加关联数据:通过Student.StudentCourses.Add关联学生和课程,EF Core自动处理外键;
    查询关联数据:通过导航属性zhangSan.StudentCourses直接获取学生选的课程,无需手动写JOIN SQL;
    基础知识拓展
  4. EF Core映射三方式对比
方式 优点 缺点 适用场景
约定优先 零配置,快速开发 灵活性差,复杂场景不适用 简单项目、原型开发
数据注解 代码简洁,直观易读 配置能力有限,耦合实体类 中等复杂度项目
Fluent API 配置灵活,解耦实体类 代码量略大 复杂项目、需精细控制映射
  1. 导航属性核心概念
    引用导航:指向单个实体(如StudentCourse.Student);
    集合导航:指向多个实体(如Student.StudentCourses);
    双向导航:实体双方都配置导航属性(如Student ↔ Course),便于双向查询;
  2. 多对多关联的简化配置(EF Core 5+)
    EF Core 5.0后支持无需中间实体的多对多关联,直接配置:
    csharp
	modelBuilder.Entity<Student>()
	.HasMany(s => s.Courses) // Student有多个Course
	.WithMany(c => c.Students) // Course有多个Student
	.UsingEntity<Dictionary<string, object>>( // 隐式中间表
	"StudentCourses", // 中间表名
	j => j.HasOne<Course>().WithMany(),
	j => j.HasOne<Student>().WithMany()
	);

总结
EF Core实体与表关联的核心是将对象模型转换为关系模型,通过约定、注解或Fluent API实现映射。导航属性是关联查询的关键,能让你用面向对象的方式操作关联数据,大幅减少SQL编写量。
实际开发中,建议优先使用Fluent API(解耦实体类),结合约定优先(减少重复配置),复杂场景再补充数据注解。掌握这些基础映射,你就能快速上手EF Core的日常开发!

本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49437.html


相关教程