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

你好,我是Eita。

Entity Framework Core (EF Core)(一个 .NET ORM 中如何建立关系

由于我主要使用 Laravel(Eloquent)进行开发,我一直以为关系需要在模型中显式定义。但
在 Laravel 中hasManybelongsTo之后,才能在 Eloquent 中将它们视为关系

然而,当我刚开始使用 EF Core 时,我感到有些不自在,
仿佛即使没有明确定义,实体之间的关系也会自动建立起来 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 查询内容及其基于约定进行解释的简要概述。
虽然存在例外情况和个别设置,但我认为这有助于全面了解关系推断。

EF核心关系图

约定和显式配置 - OnModelCreating 的作用

如前所述,EF Core 首先根据约定自动“检测和确定”实体结构中的关系。

然而,虽然按惯例推理可以减少描述的数量,

- 如果命名稍有偏差,则无法检测到。-
在一对一的情况下,无法确定从属方,可能会出现异常。-
当存在多个导航时,解释结果可能与预期不符。

有些情况下,人们的行为很难解读。

OnModelCreating来显式地修复关系的解释。
您可以显式地修复或覆盖HasMany / WithOne之类的约定解释

*注意: OnModelCreating并非仅用于设置关系。它用于
定义整个实体映射,包括表名、列名、主键、复合键、索引、必填/可选、字符数以及转换(ValueConverter) 。
由于本次的主题是关系,HasManyWithOneHasForeignKey等关系设置

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 显式设置)↓ 最终确定关系(基于外键的关系)

个人也包含
在 EF Core 中,关系并非每次都会被推断;模型首次构建时确定的内容会被缓存为 IModel,并在之后重复使用

② 缓存和重用 IModel(按 DbContext 类型)

首次(针对每个 DbContext 类型)↓ 构建并最终确定 IModel(以上所有流程均在此处执行)↓ 缓存 IModel ↓ 第二次及后续(针对相同的 DbContext 类型)↓ 获取缓存的 IModel ↓ 重用模型(关系推断/OnModelCreating 通常不会重新执行)

概括

到目前为止,我们已经了解了在 EF Core 中建立关系的过程(通过约定检测 → 根据需要进行显式配置)。
总结一下与 Laravel 的区别,EF Core 是一个 ORM,它不是“仅仅通过在模型中编写关系来建立关系”,而是“通过约定来解释类结构并构建关系

另一方面,无论你使用 EF Core 还是 Laravel,外键 (FK) 对于在数据库层面建立关系都至关重要。
这些ORM 特有的外键约定和自动补全规则,我觉得将来能够更好地理解其他 ORM 及其类似行为,同时也能找出任何不适应之处的根源。

就是这样!!

如果您觉得这篇文章有用,请点击【点赞】!
2
加载中...
2票,平均分:1.00/12
27
X Facebook Hatena书签 口袋

这篇文章的作者

关于作者

瑛塔

网页开发工程师
我想出去玩