EF Core中通过Fluent API完成对表的配置

设置实体在数据库中的表名

通过ToTable可以为数据模型在数据库中自定义表名,如果不配置,则表名为模型名的复数形式

public class EmployeeConfig:IEntityTypeConfiguration<Employee>{    public void Configure(EntityTypeBuilder<Employee> builder)    {        // 默认情况下,Employee实体在数据库中会生成Employees的数据表,这里通过ToTable(),将其指定为Employee        builder.ToTable("Employee");    }}

表间关系映射

在EF Core中,通过Fluent API做表间关系映射时,可以将API分为两类两种

两类:has和with

三种:One、Many

通过两类两种的组合,就可以完成绝大多数表间关系的映射,下面放一些常用的关系配置

public class EmployeeConfig:IEntityTypeConfiguration<Employee>{    public void Configure(EntityTypeBuilder<Employee> builder)    {        builder.ToTable(nameof(Employee));// 配置Employee表有一个Department对象,Department有多个Employee对象        // 这是典型的一对多配置        builder.HasOne(e => e.Department).WithMany(d=>d.Employees);    }}

通常配置一对多的时候只需要在一张表上进行配置就可以了,但也可以在两张表上都进行配置,这样更清晰

public class DepartmentConfig:IEntityTypeConfiguration<Department>{    public void Configure(EntityTypeBuilder<Department> builder)    {        builder.ToTable(nameof(Department));        // 配置Department表有多个Employee对象,Employee有一个Department对象        builder.HasMany(d => d.Employees).WithOne(e=>e.Department);        // 配置Department表有一个领导(也是Employee对象),领导也属于一个部门        builder.HasOne(d => d.Leader).WithOne(e => e.Department);    }}

在表关系的配置中,遵循 Has…( ).With…( )的配置方式,Has指的是配置的这张表,然后通过lambda表达式来指定对应的属性,如上面的Department表,通过lambda表达式 d => d.Employees 指定要配置的字段是Employess,HasMany则是指Department表的Employees对应多个

With则是前面has指定的属性对应的表,WithOne反过来指定了Employee表中的Department字段是一个

所以这里就是一个多对一的配置

通过这四个单词的组合,就可以完成一对多、一对一、多对多(通过中间表拆分成两个一对多)的表间关系配置

这里将Entity文件放出来,以便更好理解

public class Employee{    public Guid Id { get; set; }    public string Name { get; set; }    public bool Gender { get; set; }    public string Phone { get; set; }    public decimal Rating { get; set; }    public decimal Salary { get; set; }    public Guid DepartmentId { get; set; }    public Department Department { get; set; }}public class Department{    public Guid Id { get; set; }    public string Name { get; set; }    public Guid LeaderId { get; set; }    public Employee Leader { get; set; }    public List<Employee> Employees { get; set; }    public string NoUse { get; set; }}

主键设置

EF Core会自动将实体中名为Id的属性设置为主键,但是有时候主键并不是这么规整的命名,或者需要联合主键的情况,就需要手动指定主键

public class DepartmentConfig:IEntityTypeConfiguration<Department>{    public void Configure(EntityTypeBuilder<Department> builder)    {        // 配置数据库中主键为实体的Id字段        builder.HasKey(d => d.Id);     }}

这里指定了Department的Id字段为主键,实体属性名为Id不用手动指定,这里只是展示一下自定义的语法

public class DepartmentConfig:IEntityTypeConfiguration<Department>{    public void Configure(EntityTypeBuilder<Department> builder)    {        // 配置数据库中主键为实体的Id和Name的联合主键        builder.HasKey(d => new {d.Id, d.Name});    }}

联合主键的设置也很简单,通过new一个匿名对象的方式提供

主键的值

EF Core会默认为主键生成值,但有时候我们希望使用主键并且自己自定义相关的值,比如说自选账号、课程Id等,这时可以这样配置

public class DepartmentConfig:IEntityTypeConfiguration<Department>{    public void Configure(EntityTypeBuilder<Department> builder)    {        builder.Property(d => d.Id)        .ValueGeneratedNever(); // 配置数据库中实体的Id字段不自动生成值    }}

通过ValueGeneratedNever()可以禁用自动生成值,实际上它可以给任何一个属性都配置,但是通常只有主键是默认生成值的

外键设置

如果有外键则必须有另一个与之关联的表,所以外键配置只能在表关系配置后附加

EF Core会默认将关联表+Id的字段设置为外键,同主键一样,有时候不是那么规整,就需要手动指定

public class DepartmentConfig:IEntityTypeConfiguration<Department>{    public void Configure(EntityTypeBuilder<Department> builder)    {        builder.HasOne(d => d.Leader).WithOne(e => e.Department).HasForeignKey("LeaderId");    }}

在Department实体中指定了Leader,Leader也是Employee对象,如果依照约定属性为EmployeeId会自定设置为外键字段,但是这里指定了LeaderId,就需要手动设置外键字段为LeaderId

忽略某个字段在数据库中的映射

public class DepartmentConfig:IEntityTypeConfiguration<Department>{    public void Configure(EntityTypeBuilder<Department> builder)    {        // 数据库中忽略该字段,该字段不会存在该实体属性对应的字段        builder.Ignore(d => d.NoUse);     }}

前面Department实体中有一个NoUse字段,但是不希望它在数据库中映射该字段,就可以通过Ignore的方式忽略掉

字段约束

通过Fluent API能够对字段进行约束,这样在生成数据库表时就会将相应的约束生成,如设置了字段的最大长度在数据库表中的字段数据类型时nvarchar(设定的最大长度),如果没有设置,在数据库表中的字段数据类型则是nvarchar(max)

Fluent支持流式语法,可以将多个约定流式附加

非空约束
public class DepartmentConfig:IEntityTypeConfiguration<Department>{    public void Configure(EntityTypeBuilder<Department> builder)    {        // 设置姓名字段不为空        builder.Property(d => d.Name).IsRequired();    }}
字段最大长度
public class DepartmentConfig:IEntityTypeConfiguration<Department>{    public void Configure(EntityTypeBuilder<Department> builder)    {        // 设置姓名字段最大长度为30,且不为空        builder.Property(d => d.Name).HasMaxLength(30).IsRequired();    }}
固定长度字段
public class EmployeeConfig:IEntityTypeConfiguration<Employee>{    public void Configure(EntityTypeBuilder<Employee> builder)    {        // Phone字段在数据库中为11位固定长度字符串 IsFixedLength()用于指定该字段是否为固定长度        builder.Property(e => e.Phone).HasMaxLength(11).IsFixedLength();    }}

IsFixedLength()用于指定该字段是否为固定长度,其长度为前面设置的字段最大长度

指定字段名
public class EmployeeConfig:IEntityTypeConfiguration<Employee>{    public void Configure(EntityTypeBuilder<Employee> builder)    {        // 显式指定实体属性对应数据库中的字段名,这里指定Phone字段对应的数据库字段为ChinaPhone        builder.Property(e => e.Phone).HasColumnName("ChinaPhone");    }}
指定数据类型
public class EmployeeConfig:IEntityTypeConfiguration<Employee>{    public void Configure(EntityTypeBuilder<Employee> builder)    {        // 指定decimal的精度为5刻度为2        builder.Property(e => e.Rating).HasColumnType("decimal(5, 2)");    }}

注:关于精度和刻度的解释,精度是数字的位数,刻度是小数的位数,即decimal(5, 2)能表示的最大数是999.99,一共五位,小数两位

指定数据类型更常用的情况是将实体的decimal类型指定为数据库中的money类型

public class EmployeeConfig:IEntityTypeConfiguration<Employee>{    public void Configure(EntityTypeBuilder<Employee> builder)    {        // 指定decimal的精度为5刻度为2        builder.Property(e => e.Salary).HasColumnType("money");    }}

为什么我的Fluent API配置长这样

因为进行了分组配置,将每个类的配置分别拆分到不同的文件

具体的配置可以看看微软的官方文档

(0)

相关推荐

  • 多维分析后台实践 3:维度排序压缩

    实践目标 本期目标,是在完成数据类型转化基础上,实现维度排序压缩,进一步提升计算速度. 实践的步骤: 1. 准备基础宽表:修改上期的代码,完成维度排序压缩存成新组表. 2. 访问基础宽表:上期代码不必 ...

  • 【C#】AutoMapper 使用手册

    本文基于 AutoMapper 9.0.0 AutoMapper 是一个对象-对象映射器,可以将一个对象映射到另一个对象. 官网地址:http://automapper.org/ 官方文档:https ...

  • C# 数据操作系列 - 6 EF Core 配置映射关系

    0. 前言 在<C# 数据操作系列 - 5. EF Core 入门>篇中,我们简单的通过两个类演示了一下EF增删改查等功能.细心的小伙伴可能看了生成的DDL SQL 语句,在里面发现了些端 ...

  • EF CORE中复杂类型的映射

    实体映射时,遇到复杂类型,可选择下述方法处理: NotMapped,跳过映射 在复杂类型上声明 [Owned],但仅限该复杂类型是全部由简单值类型组成的 自定义序列化方法 示例: IPInfo使用了o ...

  • 如何在.NET Core中为gRPC服务设计消息文件(Proto)

    今天 以下文章来源于DotNET技术圈 ,作者Peter Vogel 如何在.NET Core中为gRPC服务设计消息 使用协议缓冲区规范定义gRPC服务非常容易,但从需求转换为.NET Core,然 ...

  • 如何解决在ASP.NET Core中找不到图像时设置默认图像

    dotNET跨平台 今天 以下文章来源于UP技术控 ,作者conan5566 UP技术控不止IT 还有生活 背景 web上如果图片不存在一般是打xx,这时候一般都是会设置默认的图片代替.现在用中间件的 ...

  • 一图看懂 ASP.NET Core 中的服务生命周期

    dotNET跨平台 今天 以下文章来源于技术译站 ,作者技术译民 翻译自 Waqas Anwar 2020年11月8日的文章 <ASP.NET Core Service Lifetimes (I ...

  • 如何在 ASP.Net Core 中使用 HTTP.sys WebServer ?

    dotNET跨平台 今天 以下文章来源于码农读书 ,作者码农读书 ASP.Net Core 是一个开源的,跨平台的,轻量级模块化框架,可用它来构建高性能的Web程序,大家都知道 Kestrel 是 A ...

  • Asp.Net Core 中IdentityServer4 授权中心之应用实战

    一.前言 查阅了大多数相关资料,查阅到的IdentityServer4 的相关文章大多是比较简单并且多是翻译官网的文档编写的,我这里在 Asp.Net Core 中IdentityServer4 的应 ...

  • ASP.NET Core 5.0 Web API 自动集成Swashbuckle

    dotNET跨平台 今天 以下文章来源于UP技术控 ,作者conan5566 UP技术控不止IT 还有生活 ASP.NET Core 5.0 Web API与开放源代码项目 Swashbuckle.A ...

  • 如何在 ASP.NET Core 中使用 HttpClientFactory ?

    dotNET跨平台 今天 以下文章来源于码农读书 ,作者码农读书 ASP.Net Core 是一个开源的,跨平台的,轻量级模块化框架,可用它来构建高性能的Web程序,这篇文章我们将会讨论如何在 ASP ...

  • .Net Core 中的 MurmurHash

    MurmurHash 是一种非加密型哈希算法,适用于一般的哈希检索操作,具有高性能.低碰撞率的特点.由 Google 的工程师 Austin Appleby 于2008年创建.MurmurHash 与 ...