EF中Fluent API更多配置

基本EF配置只要配置实体类和表、字段的对应关系、表间关联关系即可。如果利用EF的高级配置,可以达到更多效果:如果数据错误(比如字段不能为空、字符串超长等),会在EF层就会报错,而不会被提交给数据库服务器再报错;如果使用自动生成数据库,也能帮助EF生成更完美的数据库表。

基本步骤

在StudentConfig,实体对象的配置类中去设置指定的字符的其他配置

  1. 首先调用Property()方法获取目标字段
  2. Property()方法中使用的是Lambda表达式
  3. 获取到字段之后调用一系列EF函数设置字段的配置

字段的最大长度

HasMaxLength设定字段的最大长度
例如设置表中的Name的字段最大长度为50

 this.Property(p=>p.Name).HasMaxLength(50);

如果插入一个Person对象,Name属性的值非常长,保存的时候就会报DbEntityValidationException异常,这个异常的Message中看不到详细的报错消息,要看EntityValidationErrors属性的值。

字段是否可空

 this.Property(p => p.Pwd).IsRequired();//不为空
  this.Property(p => p.Pwd).IsOptional();//可为空(没用的鸡肋!)

EF默认规则是“主键属性不允许为空,引用类型允许为空,可空的值类型long?等允许为空,值类型不允许为空。”基于“尽量少配置”的原则:如果属性是值类型并且允许为null,就声明成long?等,否则声明成long等;如果属性属性值是引用类型,只有不允许为空的时候设置IsRequired()。

其他一般不用设置的

  1. 主键:this.HasKey(p => p.pId);
  2. 某个字段不参与映射数据库:this.Ignore(p => p.Name1);
  3. this.Property(p => p.Name).IsFixedLength(); 是否对应固定长度
  4. this.Property(p => p.Name).IsUnicode(false) 对应的数据库类型是varchar类型,而不是nvarchar
  5. this.Property(p => p.Id).HasColumnName(“Id”); Id列对应数据库中名字为Id的字段
  6. this.Property(p=>p.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity) 指定字段是自动增长类型。

流动起来

因为ToTable()、Property()、IsRequired()等方法的还是配置对象本身,因此可以实现类似于StringBuilder的链式编程,这就是“Fluent”一词的含义;

一对多关系映射

EF最有魅力的地方在于对于多表间关系的映射,可以简化工作。 复习一下表间关系:

  1. 一对多(多对一):一个班级对应着多个学生,一个学生对着一个班级。一方是另外一方的唯一。在多端有一个指向一端的外键。
    举例:
    班级表:T_Classes(Id,Name)
    学生表T_Students(Id,Name,Age,ClassId)
  2. 多对多:一个老师对应多个学生,一个学生对于多个老师。任何一方都不是对方的唯一。 需要一个中间关系表。
    具体:
    学生表T_Students(Id,Name,Age,ClassId)
    老师表 T_Teachers(Id,Name,PhoneNum)
    关系表T_StudentsTeachers(Id,StudentId,TeacherId)

和关系映射相关的方法

  1. 基本套路this.Has(p=>p.A).With***() 当前这个表和A 属性的表的关系是Has 定义, With 定义的是A 对应的表和这个表的关系。Optional/Required/Many
  2. HasOptional() 有一个可选的(可以为空的)
  3. HasRequired() 有一个必须的(不能为空的)
  4. HasMany() 有很多的
  5. WithOptional() 可选的
  6. WithRequired() 必须的
  7. WithMany() 很多的

配置一对多关系

  1. 先按照正常的单表配置把Student、ClassRoom 配置起来,Students 的ClassId 字段就对应Student类的ClassId 属性。
  2. 给Student类增加一个ClassRoom类型、名字为CRoom(不一定非叫这个,但是习惯是:外键名去掉Id)的属性,要声明成virtual(后面讲原因)
  3. 然后就可以实现各种对象间操作了:
    数据插入也变得简单了,不用再考虑“先保存Class,生成Id,再保存Student”了。这样就是纯正的“面向对象模型”,ClassId 属性可以删掉。
  4. 如果ClassId 字段可空怎么办?直接把ClassId 属性设置为long?
  5. 还可以在Class中配置一个public virtual ICollection Students { get; set; } = new List(); 属性。最好给这个属性初始化一个对象。注意是virtual。这样就可以获得所有指向了当前对象的Stuent集合,也就是这个班级的所有学生。我个人不喜欢这个属性,业界的大佬也是建议“尽量不要设计双向关系”,因为可以通过Class clz = ctx.Classes.First(); var students =ctx.Students.Where(s => s.ClassId == clz.Id);来查询获取到,思路更清晰。

猜你喜欢

转载自blog.csdn.net/dust__/article/details/106491514