7. EF Core 導航屬性配置


一、多導航屬性配型

在 Post 類中,可能需要跟蹤是文章的創建者和最后編輯者,下面是 Post 類的兩個新的導航屬性。
1、設置導航屬性方式
public class Post
{
   public int PostId { get; set; }
   public string Title { get; set; }
   public string Content { get; set; }
   public User Author { get; set; }
   public User Contributor { get; set; }
}

public class User
{
   public string UserId { get; set; }
   public string FirstName { get; set; }
   public string LastName { get; set; }

   [InverseProperty(nameof(Post.Author))] //設置反轉導航屬性
    public List<Post> AuthoredPosts { get; set; }
    [InverseProperty(nameof(Post.Contributor))] //設置反轉導航屬性
     public List<Post> ContributedToPosts { get; set; } 
}

 

在Post類設置反轉導航屬性也可以

public class Post
{
   public int PostId { get; set; }
   public string Title { get; set; }
   public string Content { get; set; }

[InverseProperty(nameof(User.AuthoredPosts))]   
public User Author { get; set; }
[InverseProperty(nameof(User.ContributedToPosts))]   
public User Contributor { get; set; } } public class User {   public string UserId { get; set; }   public string FirstName { get; set; }   public string LastName { get; set; }   public List<Post> AuthoredPosts { get; set; } public List<Post> ContributedToPosts { get; set; } }

 Post表會默認生成:“導航屬性名Id” 的外鍵  AuthorId,ContributorId

 

2.ForeignKeyAttribute方式設置
public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public User Author { get; set; }
    public User Contributor { get; set; }
}

public class User
{
    public string UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public User Author { get; set; }
    [ForeignKey("AuthorID")]
    public string ContributorID { get; set; }
    [ForeignKey("ContributorID")]
    public User Contributor { get; set; }
}

3.Fluent API方式

modelBuilder.Entity<Post>().HasOne(p => p.Author).WithMany(u=>u.AuthoredPosts).HasForeignKey("AuthorId");
modelBuilder.Entity<Post>().HasOne(p => p.Contributor).WithMany(u => u.ContributedToPosts);

二、Fluent API顯示設置外鍵

1、顯示設置外鍵

referenceCollectionBuilder.HasForeignKey(p => p.BlogForeignKey);
modelBuilder.Entity<Car>().HasKey(c => new { c.State, c.LicensePlate });  //復合主鍵設置
referenceCollectionBuilder.HasFoHasForeignKey(s => new { s.CarState, s.CarLicensePlate }) //設置有復合主鍵表的外鍵,依賴主體要定義CarState,CarLicensePlate 這兩個復合主鍵的屬性字段
referenceCollectionBuilder.HasForeignKey("BlogId");

 2、顯式設置外鍵關聯主體主鍵之外的鍵,通過 HasPrincipalKey 配置

modelBuilder.Entity<Post>().HasOne(p => p.Blog).WithMany(b => b.Posts).HasForeignKey(p 
=> p.BlogUrl).HasPrincipalKey(b => b.Url); //Post表BlogUrl字段是外鍵,關聯Blog表Url字段
modelBuilder.Entity<Post>().HasOne(p => p.Blog).WithMany(b => b.Posts).HasForeignKey(p 
=> new { p.BlogUrl, p.BlogState }).HasPrincipalKey(b => new { b.Url, b.State });

 

三、一對一關系:一對一關系兩端都是引用導航屬性,無法判斷那個作為主體實體,推薦顯式指定外鍵屬性

1、數據注解方式

public class Blog
{
 public int BlogId { get; set; }
 public string Url { get; set; }
 public BlogImage BlogImage { get; set; }
}
public class BlogImage
{
   public int BlogImageId { get; set; }
   public byte[] Image { get; set; }
   public string Caption { get; set; }
  
public int BlogId { get; set; } //顯示指定外鍵屬性,設置在Blog端也可以   public Blog Blog { get; set; } }

2、Fluent API方式:使用 HasOne 和 WithOne 方法

modelBuilder.Entity<Blog>().HasOne(p => p.BlogImage).WithOne(i => i.Blog).HasForeignKey<BlogImage>(b => b.BlogForeignKey);  //HasForeignKey<BlogImage>指定設置外鍵那一端

 

四、多對多:關系型數據庫中不支持多對多的映射,通過建立中間表連接,使用一對多的方式模擬多對多關系

public class Post
{
   public int PostId { get; set; }
   public string Title { get; set; }
   public string Content { get; set; }
   public List<PostTag> PostTags { get; set; }
}
public class Tag {   public string TagId { get; set; }   public List<PostTag> PostTags { get; set; } }  

//中間表
public class PostTag {   public int PostId { get; set; }   public Post Post { get; set; }   public string TagId { get; set; }   public Tag Tag { get; set; } } class MyContext : DbContext {   public DbSet<Post> Posts { get; set; }   public DbSet<Tag> Tags { get; set; }   protected override void OnModelCreating(ModelBuilder modelBuilder)   {     modelBuilder.Entity<PostTag>()     .HasKey(t => new { t.PostId, t.TagId }); //設置中間表主鍵
    modelBuilder.Entity
<PostTag>()     .HasOne(pt => pt.Post)     .WithMany(p => p.PostTags)     .HasForeignKey(pt => pt.PostId);
    modelBuilder.Entity
<PostTag>()     .HasOne(pt => pt.Tag)     .WithMany(t => t.PostTags)     .HasForeignKey(pt => pt.TagId);   } }

 五、自引用關系: 依賴關系和主體實體類型相同的關系

1.模型定義

  public class PictureCategory 
  { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CategoryId { get; private set; } public string Name { get; set; } public int? ParentCategoryId { get; private set; }public virtual PictureCategory ParentCategory { get; set; } //沒有virtual關鍵字,這會導致導航屬性不能加載 public virtual List<PictureCategory> Subcategories { get; set; } }

2.FluentAPI配置:在EFCore Context中重寫方法OnModelCreating配置雙向關聯(ParentCategory 和 SubCategories)

        protected override void OnModelCreating(DbModelBuilder modelBuilder) {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<PictureCategory>()
            .WithMany(cat => cat.SubCategories)
            .HasOne(cat => cat.ParentCategory)
       .HasForeignKey(cat=>cat.ParentCategoryId);
        }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM