十年河東十年河西,莫欺少年窮
學無止境,精益求精
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); } }
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); } }
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); } }
//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); } }
//單向導航屬性、並顯式指定外鍵列 builder.HasOne<Article>(A => A.article).WithMany().HasForeignKey(A => A.articleId);
以上就是CodeFitst 配置一對一 、一對多、多對多的方式
@天才臥龍的博科人