Day15:EF Core 入门 + CodeFirst(就业核心版)

一、今日任务(直接执行)

  1. Admin.NET.API 项目中集成 EF Core
  2. 理解:DbContext / DbSet / 迁移机制
  3. 掌握两种配置方式:数据注解 DataAnnotationsFluentAPI
  4. 练习:CodeFirst 创建
    • 用户表 SysUser
    • 角色表 SysRole
    • 用户角色关联表 SysUserRole
  5. 执行 Migration 生成真实数据库
  6. 高频面试题背诵

相关两篇博客(EF Core的详细教程)

.Net Core 学习:Razor Pages -- EF Core工作原理

.Net Core 学习: Razor Pages -- EF Core简介

二、第一步:安装 EF Core 包

NuGet 包管理器程序包管理器控制台 执行:

必需包 安装到对应DDD(领域驱动设计)四层架构‌

复制代码
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools

如果你用 MySQL / PostgreSQL 就换对应驱动:

  • MySQL:Pomelo.EntityFrameworkCore.MySql
  • PostgreSQL:Npgsql.EntityFrameworkCore.PostgreSQL

咱就以 SQL Server 为例(企业最常用)。

三、核心概念(10 分钟)

  1. **DbContext:**数据库上下文,相当于 MyBatis 的 SqlSessionFactory + Hibernate 的 SessionFactory。

  2. **DbSet<T>:**对应数据库中的一张表。

  3. **CodeFirst:**先写实体类 → 执行迁移命令 → 自动生成库和表。

  4. **Migration:**迁移记录:每次表结构变更都会生成一个版本文件,可回滚。

四、在项目中编写实体(Domain 层)

位置:Admin.NET.Domain新建文件夹:Entities

1. SysUser 用户表

复制代码
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Admin.NET.Domain.Entities;

public class SysUser
{
    /// <summary>
    /// 用户ID
    /// </summary>
    [Key]
    public long Id { get; set; }

    /// <summary>
    /// 账号
    /// </summary>
    [Required]
    [Column(TypeName = "varchar(50)")]
    public string Account { get; set; }

    /// <summary>
    /// 密码
    /// </summary>
    [Required]
    [Column(TypeName = "varchar(100)")]
    public string Password { get; set; }

    /// <summary>
    /// 姓名
    /// </summary>
    [Column(TypeName = "nvarchar(20)")]
    public string Name { get; set; }

    /// <summary>
    /// 状态 0=禁用 1=正常
    /// </summary>
    public int Status { get; set; } = 1;

    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime CreateTime { get; set; } = DateTime.Now;

    // 导航属性:一个用户多个角色
    public ICollection<SysUserRole> UserRoles { get; set; } = new List<SysUserRole>();
}

2. SysRole 角色表

复制代码
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Admin.NET.Domain.Entities;

public class SysRole
{
    [Key]
    public long Id { get; set; }

    /// <summary>
    /// 角色名称
    /// </summary>
    [Required]
    [Column(TypeName = "nvarchar(50)")]
    public string RoleName { get; set; }

    /// <summary>
    /// 角色编码
    /// </summary>
    [Required]
    [Column(TypeName = "varchar(50)")]
    public string RoleCode { get; set; }

    public int Status { get; set; } = 1;

    public DateTime CreateTime { get; set; } = DateTime.Now;

    // 导航属性
    public ICollection<SysUserRole> UserRoles { get; set; } = new List<SysUserRole>();
}

3. SysUserRole 用户角色关联表(多对多)

复制代码
using System.ComponentModel.DataAnnotations;

namespace Admin.NET.Domain.Entities;

public class SysUserRole
{
    [Key]
    public long Id { get; set; }

    public long UserId { get; set; }

    public long RoleId { get; set; }

    // 导航
    public SysUser User { get; set; }

    public SysRole Role { get; set; }
}

五、创建 DbContext(Infrastructure 层)

位置:Admin.NET.Infrastructure 新建文件夹:DbContexts

AppDbContext.cs

复制代码
using Admin.NET.Domain.Entities;
using Microsoft.EntityFrameworkCore;

namespace Admin.NET.Infrastructure.DbContexts;

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
    {
    }

    // 表
    public DbSet<SysUser> SysUsers { get; set; }
    public DbSet<SysRole> SysRoles { get; set; }
    public DbSet<SysUserRole> SysUserRoles { get; set; }

    // FluentAPI 配置(可选,比注解更强大)
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 联合索引/唯一键示例
        modelBuilder.Entity<SysUser>()
           .HasIndex(u => u.Account)
           .IsUnique();

        modelBuilder.Entity<SysUserRole>()
           .HasIndex(ur => new { ur.UserId, ur.RoleId })
           .IsUnique();
    }
}

六、在 API 层注入 DbContext(Program.cs)

复制代码
using Microsoft.EntityFrameworkCore;
using Serilog;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

//注入 Swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// 注入 EF Core
builder.Services.AddDbContext<AppDbContext>(options =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));//从 appsettings.json 获取数据库连接
});

//Serilog 注册(用 Serilog 替换默认日志)
builder.Host.UseSerilog((ctx, cfg) =>
{
    cfg.ReadFrom.Configuration(ctx.Configuration);// 从 appsettings.json 读取日志配置
});


var app = builder.Build();
// 中间件顺序:日志 → 异常 → 其他

//启用日志中间件
app.UseLogMiddleware();

//启用全局异常中间件
app.UseGlobalException();

//app.UseRouting();   //路由
//app.UseAuthentication();    //认证
//app.UseAuthorization(); //授权

if (app.Environment.IsDevelopment()) 
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.MapControllers();
app.Run();

appsettings.json 加连接字符串:

复制代码
"ConnectionStrings": {
  "DefaultConnection": "Server=.;Database=AdminNET;Trusted_Connection=True;TrustServerCertificate=True;"
}

七、Migration 迁移命令(必背)

打开:工具 → NuGet 包管理器 → 程序包管理器控制台 默认项目选择:Admin.NET.InfrastructureAdmin.NET.API

1. 创建迁移文件

复制代码
Add-Migration InitDb

2. 更新到数据库

复制代码
Update-Database

3. 常用命令

  • Remove-Migration:删除最后一次迁移
  • Update-Database 名称:回滚到某个版本
  • Script-Migration:生成 SQL 脚本

八、数据注解 vs FluentAPI(面试必问)

1. 数据注解(DataAnnotations)

  • 写在实体类属性上
  • 简单直观
  • 适合简单约束

常用:

  • [Key] 主键
  • [Required] 非空
  • [MaxLength(50)]
  • [Column(TypeName="varchar(50)")]
  • [ForeignKey("UserId")]

2. FluentAPI

  • OnModelCreating 中写
  • 功能更强:联合索引、多对多、复杂关系、种子数据
  • 不污染实体
  • 企业大型项目首选

九、高频面试题 + 标准答案(直接背)

1. EF Core 是什么?和 EF6 区别?

**答:**EF Core 是轻量级、跨平台的 ORM,支持 .NET Core/.NET 5+。EF6 是 Windows 版 .NET Framework 专用。EF Core 性能更好、更轻量、支持更多数据库、适合微服务。

2. CodeFirst、DbFirst、ModelFirst 区别?

答:

  • CodeFirst:先写实体,自动生成库表(企业主流)
  • DbFirst:从现有数据库生成实体
  • ModelFirst:从设计器生成模型和库表(几乎不用)

3. DbContext 生命周期?

答: ASP.NET Core 中默认 Scoped(一次请求一个实例),线程安全,适合 Web。

4. EF Core 有几种查询方式?

答:

  1. LINQ 查询语法
  2. LINQ 方法语法
  3. FromSQL 执行原生 SQL
  4. 存储过程

5. 贪婪加载、延迟加载、显式加载区别?

答:

  • 延迟加载:用到导航属性才查,默认关闭,易导致 N+1
  • 贪婪加载Include() 联表一次性查,性能好
  • 显式加载Load() 手动加载

企业优先 Include 贪婪加载

6. 什么是 EF Core 迁移?

**答:**Migration 会记录表结构变更,生成版本文件,可自动同步数据库,支持回滚,适合团队协作。

7. AsNoTracking 有什么用?

答: 关闭跟踪,查询更快,减少内存占用,只读场景强烈推荐

相关推荐
叫我黎大侠3 小时前
.NET 实战:调用千问视觉模型实现 OCR(车票识别完整教程)
阿里云·ai·c#·ocr·asp.net·.net·.netcore
van久4 小时前
Day15-4:【日志】中间件和过滤器 的对比选择
.netcore
van久1 天前
Day14: 搭建企业标准的DDD 简洁版四层架构
架构·.netcore
van久1 天前
ADay15-1: 安装 EF Core 包 到 对应DDD(领域驱动设计)四层架构‌
.netcore
时光追逐者2 天前
C#/.NET/.NET Core技术前沿周刊 | 第 69 期(2026年4.01-4.12)
c#·.net·.netcore
willhuo4 天前
基于Playwright的抖音网页自动化浏览器项目使用指南
爬虫·c#·.netcore·webview
csdn_aspnet5 天前
在 .NET Core 8 中实现 CORS
.netcore·跨域·cors·.net8
csdn_aspnet6 天前
在 ASP.NET Core (WebAPI) 中启用 CORS
后端·asp.net·.netcore
观无7 天前
Windows 本地电脑搭建一个私有的、类似 Gitee 的 Git 服务
gitee·jenkins·.netcore