zoukankan      html  css  js  c++  java
  • EF Core中通过Fluent API完成对表的配置

    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)
        {
            // 设置Salary在数据库中的类型为money(SQL Server的一个数据类型,不晓得其他数据库支持不)
            builder.Property(e => e.Salary).HasColumnType("money");
        }
    }
    

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

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

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

    分组配置

  • 相关阅读:
    关于params
    javascript判断gridview中的checkbox是否选中!
    读取Excel内容,导入数据库多张表!
    转向新页,控制页面大小并传值
    DropDownList分层显示!
    验证输入的是否数字的几种方法
    CentOS 6.5编译安装Nginx1.6.2+MySQL5.5.32+PHP5.3.27
    hdu 2425最短路
    hdu 2207水题
    hdu 3079水题
  • 原文地址:https://www.cnblogs.com/wujuncheng/p/14493987.html
Copyright © 2011-2022 走看看