公司动态
StarWars EF Core数据访问详解:StarWarsContext关系建模与数据库自动种子数据
StarWars EF Core数据访问详解StarWarsContext关系建模与数据库自动种子数据【免费下载链接】StarWarsGraphQL Star Wars example using GraphQL for .NET, ASP.NET Core, Entity Framework Core项目地址: https://gitcode.com/gh_mirrors/st/StarWarsStarWars 是一个基于 GraphQL for .NET、ASP.NET Core 与 Entity Framework Core 的经典示例项目它的核心演示了如何用 EF Core 完成完整的数据访问通过StarWarsContext关系建模整个《星球大战》数据库并在应用启动时自动注入种子数据。本文将带你快速理解这两大机制的实现细节。️ 项目分层数据流是怎么走的项目采用三层架构数据访问是其中最关键的一环层项目职责API 层StarWars.ApiGraphQL 接口、GraphiQL 界面核心层StarWars.Core领域模型与仓储接口数据层StarWars.DataEF Core 上下文、仓储实现、种子数据核心层定义了纯领域模型如 Character.cs、Human.cs、Droid.cs而数据层负责把它们映射为真实的数据库表——两者完全解耦。 StarWarsContext数据访问的统一入口StarWarsContext.cs 是继承自DbContext的数据访问上下文它通过8 个DbSet集合暴露了数据库的全部实体Episodes/Planets/Characters剧集、星球、角色Droids/Humans机器人与人类均为Character的子类CharacterFriends/CharacterEpisodes两个连接表实体用于建模多对多关系值得注意的双构造函数设计第 13-22 行参数化构造注入DbContextOptions与ILogger由 ASP.NET Core 依赖注入容器调用是生产环境的主入口无参构造直接硬编码 LocalDB 连接字符串第 28 行方便开发调试时独立创建上下文。而连接字符串的真正生产来源在 Startup.cs测试环境使用内存数据库UseInMemoryDatabase正式环境则读取appsettings.json中的ConnectionStrings:StarWarsDatabaseConnection。这让同一个上下文既能跑集成测试、又能连真实 SQL Server。 关系建模全解析OnModelCreating 中的 4 种关系EF Core 建模的核心在OnModelCreating方法中StarWarsContext.cs 第 34-83 行。它用**流畅 APIFluent API**显式声明了 4 类关系这正是初学者最常遇到的建模场景。1. 显式主键 关闭自增modelBuilder.EntityEpisode().HasKey(c c.Id); modelBuilder.EntityEpisode().Property(e e.Id).ValueGeneratedNever();Episode、Planet、Character的主键都设置为ValueGeneratedNever()第 40-49 行——即主键不由数据库生成必须由应用提供。种子数据正是借此手动指定了Id 4/5/6、Id 1/2等业务语义编号避免了自增序列与业务编号不一致的尴尬。2. 多对多关系复合主键连接表这是 EF Core 关系建模中最经典的部分。角色 ↔ 角色的朋友关系、角色 ↔ 剧集的出演关系都通过独立的连接实体实现CharacterFriend.cs含CharacterIdFriendId两个外键CharacterEpisode.cs含CharacterIdEpisodeId两个外键建模时第 52-64 行复合主键HasKey(t new { t.CharacterId, t.FriendId })两列组合唯一天然防止重复建友谊双向导航HasOne(cf cf.Character).WithMany(c c.CharacterFriends)从任一角色都能找到它的所有朋友反向也能找到谁把它列为朋友删除限制OnDelete(DeleteBehavior.Restrict)确保角色存在朋友关系时无法被删除保护数据完整性。3. 一对多关系人类与故乡星球modelBuilder.EntityHuman().HasOne(h h.HomePlanet).WithMany(p p.Humans);一行代码第 82 行建立了Human → Planet的一对多关系一个星球如 Tatooine对应多位人类居民每位人类只有一个故乡星球。EF Core 会自动在Humans表上生成HomePlanetId外键列。4. 一多对一剧集的英雄Episode模型上有一个Hero导航属性Episode.cs 第 10 行指向某位Character——这一部的英雄是谁。这条外键正是通过第三次数据库迁移 Hero.cs 添加的在Episodes表上新增可空的HeroId列并建立索引删除行为同样是Restrict。 自动种子数据启动即有数据数据库建好了第一次运行就需要满库数据。StarWars 的答案是把种子逻辑封装为扩展方法 StarWarsSeedData.cs 中的EnsureSeedData(this StarWarsContext db)并在 Startup.cs 第 77 行 的Configure管道中一行调用db.EnsureSeedData()——应用每次启动都会检查并按需补种无需手动执行任何脚本。种子数据包含什么实体数据来源3 部剧集NEWHOPE / EMPIRE / JEDI第 14-29 行2 个星球Tatooine / Alderaan第 31-44 行5 位人类Luke、Vader、Han、Leia、Tarkin第 46-117 行2 个机器人C-3POProtocol、R2-D2Astromech第 119-154 行关系数据每位角色的朋友列表 每部剧的英雄第 156-220 行其中藏着两个值得学习的工程细节① 幂等性设计每个实体类别写入前都先判断if (!db.Episodes.Any())表里已有数据就跳过。这保证了种子逻辑可以随每次启动安全执行不会重复插入、不会报错。② 严格的外键依赖顺序必须先有剧集、星球才能给人类挂上CharacterEpisodes与HomePlanet先有全部角色才能建立朋友关系最后才指定剧集英雄第 215-220 行。顺序颠倒就会触发外键约束异常。③ 全程日志可观测_logger.LogInformation(Seeding episodes)等日志第 12 行让控制台清晰打印每一步种子进度排查问题一目了然。 迁移机制Schema 如何演进数据层的Migrations目录保存了 3 次结构变更的完整历史20170215075510_Inital.cs——初始建库基础表20170305213221_Full.cs——扩展为完整数据库剧集/角色/关系表20170322183920_Hero.cs——为Episodes表添加HeroId外键。每个迁移都实现了Up/Down双向操作可随时升级或回滚这正是 EF Core 迁移优于EnsureCreated的地方结构变更可版本化、可审计、可协作。✅ 总结从 StarWars 学到的 4 个 EF Core 要点流畅 API 建模在OnModelCreating中显式声明主键、复合主键、双向导航与删除行为比依赖约定更可控多对多 连接实体用带复合主键的连接表如CharacterFriend建模EF Core 自动处理外键与级联规则种子数据 幂等扩展方法 启动时调用EnsureSeedData让数据库开箱即用且重复执行安全迁移 环境分支迁移管理 Schema 演进Test环境切内存库让同一套数据访问代码同时支撑开发与测试。掌握了这套模式你就能在任何 ASP.NET Core 项目中快速搭起结构清晰、自动初始化的 EF Core 数据访问层。【免费下载链接】StarWarsGraphQL Star Wars example using GraphQL for .NET, ASP.NET Core, Entity Framework Core项目地址: https://gitcode.com/gh_mirrors/st/StarWars创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考