之前我们使用的都是EF的默认配置。某些情况我们可能会想要进行一些自定义的修改,这就需要在OnModelCreating()中使用方法配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Major>(); }
顾名思义,OnModelCreating在Moldel创建时被EF自动调用,通过modelBuilder.Entity<T> ()就可以设置T的自定义映射细节。
包含
默认的(by convention),EF会把以下三种class映射到数据库
排除
如果想要排除掉一些属性,可以使用:
modelBuilder.Entity<Student>().Ignore(s => s.Age);
甚至可以直接ignore掉整个Entity:
modelBuilder.Ignore<Student>();
演示:查看Migration和Database……
[NotMapped] public string Age { get; set; }
Annotation在我们学习ASP.NET Model 验证时就被使用过。(演示:F12之后定位到System.ComponentModel.Annotations.dll)
注意理解:特性本身并没有什么作用,起作用的是利用反射检索特性的框架,比如:ASP.NET和EF。
默认EF会使用DbSet属性名(如果有的话),或类名(OnModelCreating()中引入),但是我们也可以自定义的指定表名列名
modelBuilder.Entity<NewStudent>().ToTable("Student");
或者,
[Table("Student")] public class NewStudent //NewStudent 对应着 Student表列名也类似:
modelBuilder.Entity<NewStudent>().Property(s => s.IsFemale) .HasColumnName("Gender");
或者,
[Column("Gender")] public bool IsFemale { get; set; }
EF对各种基本数据类型的映射都比较完美,比如C#的int自动对应SQL的int,bool对应bit……
注意EF会将DateTime自动映射成SQL中的DateTime2。
这是因为C#中DateTime的默认值是0001-01-01 00:00:00.0000000
枚举会自动转为int类型
演示:DayOfWeek Oncall
可以指定的是字符串长度(默认max)。
通过MaxLength轻松实现:
[MaxLength(50)] public string Name { get; set; }
modelBuilder.Entity<Student>(options => { options.Property(s => s.Name).HasMaxLength(50); });
还可以用字符串直接指定(简单粗暴)
modelBuilder.Entity<Student>() .Property(s => s.Oncall).HasColumnType("NVARCHAR(20)");
对于C#中有默认值的值类型属性(比如int),EF默认是映射为NOT NULL的;要想EF默认映射为可以NULL值,需要将其声明为可空类型,比如int?。
对于引用类型(如字符串),EF默认是映射为可以NULL,要想变成NOT NULL:
modelBuilder.Entity<Student>() .Property(s => s.Name).IsRequired();或者
[Required] public string Name { get; set; }
比如Age只能在0-150之间。你可以会认为使用Range特性即可:
[Range(0, 150)] //不会自动生成CHECK约束 public int Age { get; set; }但这是不行的,需要在OnModelCreating中进行配置(EF core3.0之后版本):
modelBuilder.Entity<Student>() .HasCheckConstraint("CK_Age","Age Between 0 AND 150")
演示查看生成的SQL
ALTER TABLE [dbo].[TB_Student] ADD CONSTRAINT [CK_Age] CHECK ([Age]>=(0) AND [Age]<=(150));
EF默认将Entity中的Id或者<entity>Id作为主键。如果我们要指定其他主键(不推荐,除了关系表的联合主键),可以:
modelBuilder.Entity<Student>() .HasKey(s => s.Name);
或者:
[Key] public string Name { get; set; }
联合主键因为要跨多列,所以只能设置在OnModelCreating()中:(后文详述)
modelBuilder.Entity<StudentAndTeacher>() .HasKey(st => new { st.TeacherId, st.StudentId });
除了主键,EF不会自动添加索引。
我们需要自己添加:
modelBuilder.Entity<Student>() .HasIndex(s => s.Name) .IsUnique(); //默认是非唯一的
modelBuilder.Entity<Student>() //联合键索引 .HasIndex(s=>new {s.Name, s.Age })
或者,在Entity类上(EF Core中)
[Index("Name", IsUnique = true)] public class Student
多快好省!前端后端,线上线下,名师精讲
更多了解 加: