一、约定大于配置
1.什么是“约定大于配置”:在EF Core中,程序员不需要事无巨细的对实体的每一个细节都配置到位。因为EF Core框架会根据“约定”,也就是默认的规则,自动完成我们没有指定的配置并应用到数据库中。具体有:
(1)表名采用DbContext中的对应的DbSet的属性名。
例如,实体类为Person,对应配置类中的DbSet变量名为People,则表名为People。
(2)数据表列的名字采用实体类属性的名字,列的数据类型采用和实体类属性类型最兼容的类型。
(3)数据表列的可空性取决于对应实体类属性的可空性。例如string类型默认可以为空,则该字段在数据库中就设置为可空。
(4)名字为Id的属性为主键,如果主键为short,int或者long类型,则默认采用自增字段,如果主键为Guid类型,则默认采用默认的Guid生成机制生成主键值。
二、EF Core的两种配置方式
1.对于实体的属性配置有两种方式:Data Annotation(特性)与Flunet API
2.Data Annotation:将配置以特性的形式标注在实体中。注意在使用该方法时需要引入命名空间System.ComponentModel.DataAnnotations.Schema;
优点:简单 缺点:耦合
3.Fluent API
(1)就是配置类中的代码,通过方法调用的方式完成配置
(2)缺点:复杂 优点:解耦
(3)配置类中的代码也可以写入DemoDbContext类(数据库上下文类)中,但是表一多,代码就会很多,这个类就会显得臃肿。
4.这两种方式大部分功能重合,但是不建议混用,日常开发建议使用Fluent API。
5.优先级:Fluent API>标注>约定
三、Fluent API属性配置
1.视图与实体类映射:
modelBuilder.Entity<Blog>().ToView("blogsView");
注意:一般来说,表中存在过多的视图时,可以认为这个数据库设计的有问题。
2.排除属性映射:
modelBuilder.Entity<Blog>().Ignore(b=>b.Name2);
例如:我想让Book这个实体类中存在一个名为Age的属性,但是不需要对数据库进行修改,可以在配置类中使用这个方法。
为Book类添加Age1与Age2两个Int字段,其中只把Age1同步到数据库中而忽略Age2:
添加字段:
在配置类中忽略Age2字段:
同步更改到内存:执行数据库迁移操作:
PM> Add-Migration AddAge1
更新数据库:
PM> Update-Database
更新后的数据库中只有Age1,无Age2
3.配置列名:modelBuilder.Entity<T>.Property(b=>b.TKey).HasColumnName("colname");
列名默认采用属性名,可以用该方法改变映射的列名
4.配置列数据类型:
builder.Property(e =>e.Title).HasColumnType("varchar(200)")
注意:一般使用nvarchar,因为varchar不能存中文
5.配置列数据的默认值:HasDefaultValue(为属性设定默认值)
modelBuilder.Entity<Student>).Property(b => b.Age).HasDefaultValue(6);
例如将Bird的Name设置默认值“bird”:同样在配置类中进行设置:
6.用EF Core太多高级特性的时候谨慎,尽量不要和业务逻辑混合在一起。比如Ignore、Shadow、Table Splitting等…
注意:在EF Core所提供的这些API中,绝大多数都支持字符串与Lambda表达式两种参数传递方式。推荐使用Lambda表达式,因为使用Lambda表达式可以利用C#的类型检查机制以及自动完成功能,避免出错
四、Fluent API表配置
1.对数据库中的每一张表可以使用HasComment(string)来给表加注释:
执行数据迁移,在下图中可以看到表注释:【表】|【属性】|【扩展属性】
2.排除某张表的迁移:
(1)在DbContext类中不把这个实体类放进去
(2)通过Fluent API 排除迁移:
modelBuilder.Ignore
: