当前位置: 首页 > 图灵资讯 > 技术篇> EF CodeFirst系列(4)---FluentApi

EF CodeFirst系列(4)---FluentApi

来源:图灵教育
时间:2023-06-06 09:25:40

阅读目录

  • Fluentapi总结
    • 1.Fluentapi简介
    • 2.实体相关配置
    • 3.属性相关配置


回到顶部

Fluentapi总结

1.Fluentapi简介

  FluentApi在EF中的作用是通过配置领域类来覆盖默认协议。在EF中,我们通过Dbmodelbuilder类使用FluentApi,其功能比数据注释属性更强大。

使用Fluentapi时,我们在contextonmodelcreating()方法中重写配置项,一个栗子:

public class SchoolContext: DbContext {    public DbSet<Student> Students { get; set; }            protected override void OnModelCreating(DbModelBuilder modelBuilder)    {        //Write Fluent API configurations here    }}

  我们可以使用FluentApi和数据注释属性,当FluentApi和数据注释属性配置相同的项目时,FluentApi中的配置。

FluentApi在EF6中可以配置以下几个方面,下表还列出了一些常用的FluentApi方法及其功能:

配置

Fluent API方法

作用

与结构相关的配置

HasDefaultSchema()

默认架构的数据库

ComplexType()

将一个类配置为复杂类型

实体相关配置

HasIndex()

实体索引

HasKey()

实体主键(可实现复合主键,[Key]复合主键不能在EFcore中实现)

HasMany()

一对多或多对多关系

HasOptional()

可选关系将在数据库中生成可空外键

HasRequired()

这样,配置就会在数据库中生成一个不能空的外键

Ignore()

实体或实体的属性不反映在数据库中

Map()

设置一些优先配置

MapToStoredProcedures()

实体的CUD操作使用存储过程

ToTable()

为实体设置表名

属性相关配置

HasColumnAnnotation()

注释属性设置

IsRequired()

在调用SaveChanges()方法时,属性不能为空

IsOptional()

可选,在数据库中生成可空列

HasParameterName()

该属性存储过程中的参数名配置

HasDatabaseGeneratedOption()

如何生成配置数据库中对应列的值,如计算、自增等

HasColumnOrder()

配置数据库中对应列的排列顺序

HasColumnType()

配置数据库中对应列的数据类型

HasColumnName()

配置数据库中对应列的列

IsConcurrencyToken()

乐观并发检测应用于配置数据库中的对应列

2.实体相关配置1.实体简单配置

栗子直接上:

我们新建了EF6Demo控制台应用程序,添加Student和Grade实体,以及上下文类ScholContext,代码如下:

//学生类    public class Student    {        public int StudentId { get; set; }        public string StudentName { get; set; }        public string StudentNo { get; set; }        public virtual Grade Grade{get;set;}    }   //年级类   public class Grade    {        public int GradeId { get; set; }        public string GradeName { get; set; }        public virtual ICollection<Student> Students { get; set; }    }    ///上下文类    public class SchoolContext:DbContext    {        public SchoolContext() : base()        {        }        public DbSet<Student> Students { get; set; }        public DbSet <Grade> Grades { get; set; }        protected override void OnModelCreating(DbModelBuilder modelBuilder)        {                       modelBuilder.HasDefaultSchema("Admin");//添加默认架构名称            modelBuilder.Entity<Student>().ToTable("StudentInfo");            modelBuilder.Entity<Grade>().ToTable("GradeInfo","NewAdmin");//设置表名和架构        }    }

在Main函数中执行代码:

class Program    {        static void Main(string[] args)        {            using (SchoolContext context=new SchoolContext())            {                context.Students.Add(new Student() { StudentId = 1, StudentName = "Jack" });                context.SaveChanges();            }        }    }

此时,在内置的SqlServer中生成数据库,如下图所示,我们可以看到Student表名为Studentinfo,结构为Admin;Grade表名为Gradeinfo,结构为Newadmin,涵盖默认协议(默认表名为dbo.Students和dbo.Grades)

EF CodeFirst系列(4)---FluentApi_表名

2.实体映射多张表

有时候我们希望一个物理属性分为两个表,那么如何配置呢?还用上面的栗子,我们把学生的名字和身份证放在一张表里,学号和身份证放在另一张表里,代码如下:

public class SchoolContext:DbContext    {        public SchoolContext() : base()        {        }        public DbSet<Student> Students { get; set; }        public DbSet <Grade> Grades { get; set; }        protected override void OnModelCreating(DbModelBuilder modelBuilder)        {       modelBuilder.Entity<Student>().Map(m =>        {          //配置第一张表,包括学生ID和学生姓名          m.Properties(p => new { p.StudentId, p.StudentName });          m.ToTable("StudentInfo");        }).Map(m =>        {          //配置第二张表,包括学生ID和学生学号          m.Properties(p => new { p.StudentId, p.StudentNo });          m.ToTable(Studentinfo2);         });       ///配置年级表名            modelBuilder.Entity<Grade>().ToTable("GradeInfo");        }    }

运行Main函数,生成新的数据库,如下所示:/p>

EF CodeFirst系列(4)---FluentApi_数据库_02

我们可以看到,通过Map(),我们将Student实体的属性分为两个表。modelBuilder.Entity<T>()方法返回Entitytypeconfiguration<T>类型,Map()方法的参数是一种委托类型,委托的输入参数是EntityMapingConfiguration的实例。下面的代码运行后生成的数据库和上面一样,我们可以定制一个委托来实现配置:

public class SchoolContext : DbContext    {        public SchoolContext() : base()        {        }        public DbSet<Student> Students { get; set; }        public DbSet<Grade> Grades { get; set; }        protected override void OnModelCreating(DbModelBuilder modelBuilder)        {            ///首先定义Action委托备用,委托的输入参数是实体映射配置(EntityMappingConfiguration)的实例            Action<EntityMappingConfiguration<Student>> studentMapping = m =>            {                m.Properties(p => new { p.StudentId, p.StudentNo });                m.ToTable(Studentinfo2);            };            modelBuilder.Entity<Student>()                ///第一张表Map()方法参数委托delegate形式                .Map(delegate (EntityMappingConfiguration<Student> studentConfig)                {                    ///map参数lambda表达式                    studentConfig.Properties(p => new { p.StudentId, p.StudentName });                    studentConfig.ToTable("StudentInfo");                 })                 ///第二张表Map()方法参数委托Action                .Map(studentMapping);                       modelBuilder.Entity<Grade>().ToTable("GradeInfo");        }    }

3.属性相关配置

属性配置比较简单,这里简单总结了主键、列基本属性、是否可空、数据长度、高并发配置。

一个栗子:

public class Student{    public int StudentKey { get; set; }//主键    public string StudentName { get; set; }//姓名    public DateTime DateOfBirth { get; set; }//生日    public byte[]  Photo { get; set; }//照片    public decimal Height { get; set; }//身高    public float Weight { get; set; }//体重            public Grade Grade{ get; set; }//年级}    public class Grade{    public int GradeKey { get; set; }//主键    public string GradeName { get; set; }//年级名        public ICollection<Student> Students { get; set; }}

使用FluentApi对领域类进行以下配置:

public class SchoolContext : DbContext    {        public SchoolContext() : base()        {        }        public DbSet<Student> Students { get; set; }        public DbSet<Grade> Grades { get; set; }        protected override void OnModelCreating(DbModelBuilder modelBuilder)        {            //设置默认架构            modelBuilder.HasDefaultSchema("Admin");            //设置主键            modelBuilder.Entity<Student>().HasKey<int>(s => s.StudentKey);                        ///设置非映射属性            modelBuilder.Entity<Student>().Ignore(s => s.Height);                        //设置Dateofbirth            modelBuilder.Entity<Student>().Property(p => p.DateOfBirth)                .HasColumnName("birthday")    //列为birthday                .HasColumnType(datetime2)   ///数据类型为datetime类型                .HasColumnOrder(3)            //顺序编号为3                .IsOptional();                //可以是null            //设置姓名            modelBuilder.Entity<Student>().Property(s => s.StudentName)                .HasMaxLength(20)             //最长20                .IsRequired()                 ///不能是null                .IsConcurrencyToken();        ///用于乐观并发检测,delete或update时,将此属性添加到where上,以判断它是否并发                      }    }

执行程序后生成的数据库如下:

EF CodeFirst系列(4)---FluentApi_表名_03

作者:捕捉月亮的猴子