2020-03-30 17:50 表之间的关系

2020-05-21  本文已影响0人  daiwei_9b9c

关系

提纲: 比较多

  1. 关系\导航属性\自引用关系
  2. 每一个关系都会在相关实体中建立一个外键
  3. FluentApi 的作用(什么情况只能使用 FluentAPI)

术语

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}
public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

关系

默认情况下,当在某个类型上发现导航属性时,将创建一个关系。

如何判断某一个属性是导航属性?
如果属性指向的类型不能由当前的数据库提供程序映射为标量类型,则该属性视为一个导航属性。

完全定义关系

最常见的模式是在关系两端定义导航属性,在依赖实体类中定义外键。

如果找不到和上面所匹配的属性并且没有使用 FluentApi 定义外键字段时,则 EFCORE 将自动产生一个外键属性
属性名称为:

单个导航属性

例如, Blog中有 public List<Post> Posts { get; set; } , 而 Post中没有任何指向 Blog 的属性

例如, Post中有 public Blog Blog { get; set; } , 而 Blog 中没有任何指向 Post 的属性

如上所述,也将产生一个外键属性, 此外键属性为隐藏外键属性

FluentApi中的方法:

使用 FluentApi 一般情形下没有必要,因为 EFCore 会自动寻找关系,并在相关表中产生外键.
除非:

  1. 需要自己指定关联关系的属性名称 (如果存在此属性)

使用 BlogForeignKey 属性作为关联字段
[ForeignKey("BlogForeignKey")] public Blog Blog { get; set; } 或者
modelBuilder.Entity<Post>() .HasOne(p => p.Blog) .WithMany(b => b.Posts) .HasForeignKey(p => p.BlogForeignKey);

  1. 关联关系为一个影子外键, 即列在类中不存在,但是在表中存在

列 BlogForeignKey 在 Post 中没有对应的属性,

modelBuilder.Entity<Post>().Property<int>("BlogForeignKey");
modelBuilder.Entity<Post>().HasOne(p => p.Blog).WithMany(b => b.Posts).HasForeignKey("BlogForeignKey");
  1. 需要自己指定外键的约束名称

modelBuilder.Entity<Post>() .HasOne(p => p.Blog) .WithMany(b => b.Posts) .HasForeignKey(p => p.BlogId) .HasConstraintName("ForeignKey_Post_Blog");

  1. 关联到组合主键
modelBuilder.Entity<Car>().HasKey(c => new { c.State, c.LicensePlate });
modelBuilder.Entity<RecordOfSale>().HasOne(s => s.Car).WithMany(c => c.SaleHistory)
  .HasForeignKey(s => new { s.CarState, s.CarLicensePlate });

5 没有导航属性,也需要建立关系

Post 和 Blog 2个类相互间没有任何关联关系
modelBuilder.Entity<Post>() .HasOne<Blog>() .WithMany() .HasForeignKey(p => p.BlogId);

  1. 关联到非主键 ( 备用健 )

modelBuilder.Entity<RecordOfSale>() .HasOne(s => s.Car) .WithMany(c => c.SaleHistory) .HasForeignKey(s => s.CarLicensePlate) .HasPrincipalKey(c => c.LicensePlate);

  1. 一对一时,需要使用 FluentApi 定义主表

modelBuilder.Entity<Blog>() .HasOne(b => b.BlogImage) .WithOne(i => i.Blog) .HasForeignKey<BlogImage>(b => b.BlogForeignKey);

  1. 一个表存在对另一个表的多个关系

ReferenceCollectionBuilder<Blog, Post> 实例 ( 一对反向导航的构建类 )

下面代码都定义一对反向导航关系,返回 ReferenceCollectionBuilder<Blog, Post> 实例

modelBuilder.Entity<Post>().HasOne(p => p.Blog).WithMany(b => b.Posts);
modelBuilder.Entity<Blog>().HasMany(b => b.Posts).WithOne(x => x.Blog);

下面代码定义了 2个单向导航属性

返回 ReferenceCollectionBuilder<Blog, Post> 实例

表示 Blog 中有 List<Post> posts 属性, 而 Post 中没有 指向 Blog 的 属性
modelBuilder.Entity<Blog>().HasMany(b => b.Posts).WithOne();
表示 Post 中有 Blog blog 属性, 而 Blog 中没有 指向 Post 的 属性
modelBuilder.Entity<Post>().HasOne(b => b.Blog).WithMany();

上一篇 下一篇

猜你喜欢

热点阅读