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 配置一對一 、一對多、多對多的方式

@天才臥龍的博科人

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