Net5 EFCore CodeFirst FluentApi关系配置

十年河东十年河西,莫欺少年穷

学无止境,精益求精  

codefirst 中如果要建立两张表的主外键关系,该如何操作呢?

在EfCore 中实体关系的配置主要有3中模式

一对一 :HasOne(....).WithOne(....)

一对多 :HasOne(....).WithMany(....)

多对多 :HasMany(....).WithMany(....)

1、一对多关系【双向导航属性】

项目中新建两张表,一张为新闻表,一张为评论表,一篇新闻对应多个评论

    //文章
    public class Article
    {
        public long id { get; set; }
        public string title { get; set; } 
        public string info { get; set; }
        public DateTime pubdate { get; set; }
        public List<Comment> comments { get; set; } = new List<Comment>();
    }
    //评论
    public class Comment
    {
        public long id { get; set; }
        public string uname { get; set; }
        public string message { get; set; } 
        public Article articleId { get; set; }
    }

1.1、配置一对多关系

(方式1)

    public class ArticleConfig : IEntityTypeConfiguration<Article>
    {
        public void Configure(EntityTypeBuilder<Article> builder)
        {
            builder.ToTable("T_Articles");
            builder.HasMany<Comment>(A => A.comments).WithOne(A => A.articleId);
        }
    }

    public class CommentConfig : IEntityTypeConfiguration<Comment>
    {
        public void Configure(EntityTypeBuilder<Comment> builder)
        {
            builder.ToTable("T_Comments");
            builder.Property("uname").HasMaxLength(50).IsRequired(true).HasComment("评论者姓名");
        }
    }

    public class wechatDbContext : DbContext
    {
        public DbSet<Article> Articles { get; set; }
        public DbSet<Comment> Comments { get; set; } 

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseSqlServer("Data Source=LAPTOP-84R6S0FB;Initial Catalog=demo1;Integrated Security=True");

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            //从当前程序集命名空间加载所有的IEntityTypeConfiguration
            modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
        }
    }
View Code
builder.HasMany<Comment>(A => A.comments).WithOne(A => A.articleId);

(方式2) 

 builder.HasOne<Article>(A => A.articleId).WithMany(A => A.comments);

1.2、显式指定外键列

    //文章 一对多
    public class Article
    {
        public long id { get; set; }
        public string title { get; set; } 
        public string info { get; set; }
        public DateTime pubdate { get; set; }
        public List<Comment> Comments { get; set; } = new List<Comment>();
    }
    //评论  一对多
    public class Comment
    {
        public long id { get; set; }
        public string uname { get; set; }
        public string message { get; set; }
        public long articleId { get; set; }
        public Article article { get; set; } 
    }

配置关系并指定外键列

    public class ArticleConfig : IEntityTypeConfiguration<Article>
    {
        public void Configure(EntityTypeBuilder<Article> builder)
        {
            builder.ToTable("T_Articles");
            //显式指定外键列
            builder.HasMany<Comment>(A => A.Comments).WithOne(A => A.article).HasForeignKey(A => A.articleId);
        }
    }

建议使用这种显式指定外键列的方式进行

2、配置一对一关系

假设一篇文章只允许一条评论

实体模型对应关系如下【一对一关系需要显示指定外键】:

    //文章 一对一
    public class Article
    {
        public long id { get; set; }
        public string title { get; set; } 
        public string info { get; set; }
        public DateTime pubdate { get; set; }
        public Comment comment { get; set; }
    }
    //评论 一对一
    public class Comment
    {
        public long id { get; set; }
        public string uname { get; set; }
        public string message { get; set; }
        public long articleId { get; set; }
        public Article article { get; set; }
        public long acticleId { get; set; }
    }

(方式一)

    public class ArticleConfig : IEntityTypeConfiguration<Article>
    {
        public void Configure(EntityTypeBuilder<Article> builder)
        {
            builder.ToTable("T_Articles"); 
        }
    }

    public class CommentConfig : IEntityTypeConfiguration<Comment>
    {
        public void Configure(EntityTypeBuilder<Comment> builder)
        {
            builder.ToTable("T_Comments");
            builder.Property("uname").HasMaxLength(50).IsRequired(true).HasComment("评论者姓名");

            builder.HasOne<Article>(A => A.article).WithOne(d => d.comment).HasForeignKey<Comment>(A => A.acticleId);

        }
    }

    public class wechatDbContext : DbContext
    {
        public DbSet<Article> Articles { get; set; }
        public DbSet<Comment> Comments { get; set; } 

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseSqlServer("Data Source=LAPTOP-84R6S0FB;Initial Catalog=demo2;Integrated Security=True");

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            //从当前程序集命名空间加载所有的IEntityTypeConfiguration
            modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
        }
    }
View Code
builder.HasOne<Article>(A => A.article).WithOne(d => d.comment).HasForeignKey<Comment>(A => A.acticleId); 

(方式二)

  builder.HasOne<Comment>(A => A.comment).WithOne(d => d.article).HasForeignKey<Comment>(A => A.acticleId);

 

 

 3、配置多对多关系

一个老师有多个学生,一个学生有多个老师

    //老师 多对多
    public class Teacher
    {
        public long id { get; set; }
        public string tname { get; set; }    
        public List<Student> students { get; set; }
    }
    //学生 多对多
    public class Student
    {
        public long id { get; set; }
        public string sname { get; set; }
        public List<Teacher>  teachers { get; set; }
    }

(方式一)

    public class ArticleConfig : IEntityTypeConfiguration<Teacher>
    {
        public void Configure(EntityTypeBuilder<Teacher> builder)
        {
            builder.ToTable("T_Teachers");
            //T_Students_Teachers 为中间表  在数据库中 多对多必须存在中间表
            builder.HasMany<Student>(A => A.students).WithMany(d => d.teachers).UsingEntity(A => A.ToTable("T_Students_Teachers"));

        }
    }

    public class CommentConfig : IEntityTypeConfiguration<Student>
    {
        public void Configure(EntityTypeBuilder<Student> builder)
        {
            builder.ToTable("T_Studentss");

          //  builder.HasMany<Teacher>(A => A.teachers).WithMany(d => d.students).UsingEntity(A => A.ToTable("T_Students_Teachers"));
        }
    }

    public class wechatDbContext : DbContext
    {
        public DbSet<Teacher> teachers { get; set; }
        public DbSet<Student>  students { get; set; } 

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseSqlServer("Data Source=LAPTOP-84R6S0FB;Initial Catalog=demo4;Integrated Security=True");

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            //从当前程序集命名空间加载所有的IEntityTypeConfiguration
            modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
        }
    }
View Code
//T_Students_Teachers 为中间表名称  在数据库中 多对多必须存在中间表
  builder.HasMany<Student>(A => A.students).WithMany(d => d.teachers).UsingEntity(A => A.ToTable("T_Students_Teachers"));

(方式二)

    public class CommentConfig : IEntityTypeConfiguration<Student>
    {
        public void Configure(EntityTypeBuilder<Student> builder)
        {
            builder.ToTable("T_Studentss");

           builder.HasMany<Teacher>(A => A.teachers).WithMany(d => d.students).UsingEntity(A => A.ToTable("T_Students_Teachers"));
        }
    }

 4、一对多关系配置【单向导航】

使用场景,

假设我们有用户表、请假表、离职表、入职表、婚假表等,其他表都需要使用到用户表,如果此时我们使用双向导航属性,则会使用户表过于复杂,因此,此时需要单向导航属性

    //文章 一对多[单向导航]
    public class Article
    {
        public long id { get; set; }
        public string title { get; set; } 
        public string info { get; set; }
        public DateTime pubdate { get; set; }
    }
    //评论  一对多[单向导航]
    public class Comment
    {
        public long id { get; set; }
        public string uname { get; set; }
        public string message { get; set; }
        public long articleId { get; set; }
        public Article article { get; set; } 
    }

此时,Article 无需引用评论表

    public class ArticleConfig : IEntityTypeConfiguration<Article>
    {
        public void Configure(EntityTypeBuilder<Article> builder)
        {
            builder.ToTable("T_Articles");
        }
    }

    public class CommentConfig : IEntityTypeConfiguration<Comment>
    {
        public void Configure(EntityTypeBuilder<Comment> builder)
        {
            builder.ToTable("T_Comments");

            //显式指定外键列
            builder.HasOne<Article>(A => A.article).WithMany().HasForeignKey(A => A.articleId);
        }
    }

    public class wechatDbContext : DbContext
    {
        public DbSet<Article> Articles { get; set; }
        public DbSet<Comment> Comments { get; set; } 

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseSqlServer("Data Source=LAPTOP-84R6S0FB;Initial Catalog=demo1;Integrated Security=True");

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            //从当前程序集命名空间加载所有的IEntityTypeConfiguration
            modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
        }
    }
View Code

  //单向导航属性、并显式指定外键列
  builder.HasOne<Article>(A => A.article).WithMany().HasForeignKey(A => A.articleId);

 

 以上就是CodeFitst 配置一对一 、一对多、多对多的方式

@天才卧龙的博科人

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章