4.2EF Core的实体类配置
本文主要讨论实体类和数据表是如何映射的,以及实体类中的属性是如何与数据表中的列映射的。
预定大于配置
EF Core会默认按照约定根据实体类和DbContext上下文类的定义来实现和数据库表的映射配置,除非用户指定了配置规则,简而言之:默认
主要规则如下:
- 数据库名采用上下文类中对应的DbSet的属性名
- 数据库表列的名字采用实体类属性的名字,列的数据类型采用和实体类属性类型兼容的类型。string->nvarchar;long->bigint
- 数据库表列的可空性取决于对应实体类属性的可空性
- 名字为Id的属性为主键,如果主键为short、int、long类型,则自动增长
Data Annotation
使用.net提供的Attribute对实体类、属性进行标注,来实现实体类的配置。
[Table("T_Books")] //将数据库表名设置为T_Books
publicclassBook
{
publiclongId { get; set; }//主键
//将Title属性最大长度设置为50,且不能为空
[MaxLength(50)]
[Required]
publicstringTitle { get; set; }//标题
publicDateTimePubTime { get; set; }//发布日期
publicdoublePrice { get; set; }//单价
[MaxLength(20)]
[Required]
publicstringAuthorName { get; set; }//作者名字
}
Fluent API
编写实现了IEntityTypeConfiguration接口的实体配置类,前面说的4.1节案例就是使用的这种,详见4.1EF Core。
- 视图与实体类映射
modelBuilder.Entity<Blog>().ToView("blogsView");
将数据库视图blogsView与Blog映射
- 排除属性映射
默认情况,一个实体类的所有属性都会映射到数据库表中,使用Ignore忽略某些属性
modelBuilder.Entity<Blog>().Ignore(b=>b.name);
//将name属性排除
- 数据库表列名称改变
默认和属性名相同,可以使用HasColumnName进行改变
modelBuilder.Entity<Blog>().Property(b=>b.BlogId).HasColumnName(blog_id);
将BlogID改为blog_id
- 列的数据类型
Title为string类型,默认生成nvarchar类型,通过下面语句改为varchar类型
builder.Property(e=>e.Title).HasColumnType("varchar(200)");
- 主键
默认把Id或者实体类型+Id属性作为主键。下面可以把Number设置为主键。
modelBuilder.entity(Student)().HasKey(c=>c.Number);
- 索引
将Blog实体类的Url属性定义为索引
modelBuilder.Entity<Blog>().HasIndex(b=>b.Url);
复合索引,将Person实体类的FirstName和LastName定义为复合索引
modelBuilder.Entity<Person>().HasIndex(p=>new {p.FirstName,p.LastName})
默认情况下,定义的索引不是唯一索引,可以使用IsUnique
把索引配置为唯一索引,还可以使用IsClustered
把索引设置为聚集索引。
注意:以上凡是modelBuilder开头的都是在上下文类进行设置,而builder类开头则是在实体配置类中进行设置。某些设置可以在两个类中都可以。例如:
//两者意义相同
builder.HasIndex(b=>b.Url);
modelBuilder.Entity<Blog>().HasIndex(b=>b.Url);
主键类型
通常使用自增long类型,新插入数据后会自动增长,但是自增系列的值一般由数据库生成,只能把数据保存后才能获得主键的值。所以通常使用一下两种方式作为主键。
- Guid类型
由于guid的值是不连续的,所以不能将guid的主键设置为聚集索引。
class Author
{
public Guid Id {set;get;}
public string name {set; get;}
}
Author a = new Author{Name = "张三"}
ctx.Authors.add(a);
await ctx.SaveChangesAsync;
- 自增+Guid类型
自动主键和Guid结合的方式,guid列只作为逻辑主键。