[C#] Entity Framework Core - 关系建立条件 -

目录
你好,我是Eita。
.NET 的 ORM Entity Framework Core (EF Core) 中建立关系
到目前为止,我主要使用 Laravel(Eloquent)进行开发,所以我的印象是关系是“在模型中显式定义和使用”的东西。
在 Laravel 中 hasMany 或 belongsTo 之后,才能在 Eloquent 中将某些东西视为关系
然而,当我第一次接触 EF Core 时,我感到“即使没有明确定义,关系也会自动建立”。 有些不安,因为
在 EF Core 中,实体之间的关系会根据导航属性和命名约定自动推断。
换句话说,有些情况下,关系会在没有明确声明的情况下建立。
本文将重点讨论在 EF Core 中建立关系的条件。
- 由什么决定这种关系?
- 如果这种关系没有明确定义,会发生什么?
我们来看一下。
EF核心中的关系基本上以三种模式建立。
EF Core 会自动从实体类的结构中解析关系。
通常,关系会以以下三种模式被检测到:
1. 仅导航
2. 仅外接按键
3. 导航+外接按键
*但是,如果命名或结构不明确,则可能无法检测到关系,或者可能会出现异常。
导航仅
public class Post { public int Id { get; set; } public User User { get; set; } // 导航 }
User 的 ,EF Core 也足以将其解释为“导航到相关实体”。
在这种情况下,即使类中不存在相应的外键,EF Core 也会在内部 一个影子属性 生成
仅限外键
public class Post { public int Id { get; set; } public int UserId { get; set; } // 外键 }
符合约定的属性(例如 UserId)潜在的外键会被识别为
即使没有导航关系,它们也会被视为关联关系。
导航键 + 外键
public class Post { public int Id { get; set; } public int UserId { get; set; } // 外键 public User User { get; set; } // 导航 }
同时存在外键和引用导航使得 EF Core 能够更轻松地根据约定解释关系。
虽然关系本身可以通过其中任何一种方式建立,但同时使用两者可以更清晰地表达意图,并减少推断过程中的歧义。
那么,为什么只需要这些就够了呢?接下来,让我们一探究竟。
它为什么有效?(推理机制)
简而言之,关系信息会根据实体类(定义表结构的类)自动注册到内部模型(IModel)中。
此自动化注册过程采用 约定俗成的方法 。
EF Core 通过组合实体类中的以下信息来确定关系:
- 属性名称(命名规则)
- 属性类型(与主键兼容的类型)
- 结构(导航/集合存在/不存在)
基于这三点,公司内部会登记建立恋爱关系。
换句话说,EF Core 并非“不写入”任何内容;而是根据规则“解释”它。
这才是人际关系形成的真正本质。
下表大致概述了 EF Core 根据其约定分析的内容及其解释方式。
虽然存在例外情况和个别设置,但我认为它对于理解关系推理的整体架构非常有用。

约定和显式配置 - OnModelCreating 的作用
如前所述,EF Core 首先根据约定自动“检测和确定”实体结构中的关系。
然而,虽然按惯例推理可以减少描述的数量,
- 如果命名稍有偏差,可能无法被检测到。-
一对一关系可能存在例外,因为无法确定依赖项。-
如果存在多个导航,其解释可能与预期不同。
有些情况下,人们的行为很难解读。
在这种情况下,如果您想要明确地固定关系的解释,可以使用 OnModelCreating 。
HasMany / WithOne 约定的解释。 明确地固定或覆盖 您可以
*需要澄清的是,OnModelCreating 并非仅用于关系设置。它用于
包括表名、列名、主键、复合键、索引、必填/可选字段、字符计数以及转换(ValueConverter)定义整个实体映射,。
由于本次的主题是关系,HasMany 、 WithOne 和 HasForeignKey 我们将重点讲解
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<User> () .HasMany(u => u.Posts) .WithOne(p => p.User) .HasForeignKey(p => p.UserId); }
如果你遵守规则,就不需要写出来,但在以下情况下,最好还是写清楚:
- 未遵循命名规范
- 我们希望明确定义一对一关系
- 我们希望修复外键名称
- 我们希望控制级联行为
- 我们希望消除歧义关系(明确意图)
- 我们希望提高团队内部代码的可读性
一旦我们明确了约定和显式配置之间的关系,EF Core 中的关系就按以下顺序确定:
首先,在初始模型构建过程中如何确定关系的 过程
① 首次构建模型时运行的过程(关系确定流程)
加载实体类结构(导航/外键/命名)↓ 使用约定推断关系 ↓ 在内部模型 (IModel) 中注册 ↓ OnModelCreating(使用 Fluent API 显式设置)↓ 最终确定关系(基于外键的关系)
另外,我个人也包含关系在内的模型定义(IModel)何时最终确定 も気になったので、補足として置いておきます。
在 EF Core 中,关系并非每次都会重新推断;而是在初始模型构建期间确定的内容会被缓存为 IModel,并在之后重复使用。
② 缓存和重用 IModel(按 DbContext 类型)
首次(针对每个 DbContext 类型)↓ 构建并最终确定 IModel(以上所有流程均在此处执行)↓ 缓存 IModel ↓ 第二次及后续(针对相同的 DbContext 类型)↓ 获取缓存的 IModel ↓ 重用模型(关系推断/OnModelCreating 通常不会重新执行)
概括
到目前为止,我们已经了解了在 EF Core 中建立关系的过程(通过约定检测 → 根据需要进行显式配置),同时组织了信息。
用一句话概括它与 Laravel 的区别:EF Core 并非 “仅仅因为你在模型中编写了关系就建立关系”,而是“通过使用约定来解释类结构,从而构建关系 。
另一方面,无论你使用的是 EF Core 还是 Laravel,外键 (FK) 对于在数据库层面建立关系都至关重要。
这些 ORM 特有的关于外键的约定和自动补全规则, 将有助于你在未来遇到其他 ORM 或类似行为时,更容易理解和解决任何不一致之处。
就是这样!!
3
