美文网首页
2020-03-30 17:50 表之间的关系

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

作者: daiwei_9b9c | 来源:发表于2020-05-21 20:38 被阅读0次

关系

提纲: 比较多

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

术语

  • 主体实体: 这是包含主/备用键属性的实体。 有时称为关系的 "父项"。例如下面的 Blog
  • 主体健: 唯一标识主体实体的属性。 这可能是主键或备用健。例如下面Blog.BlogId
  • 相关实体(依赖实体): 这是包含外键属性的实体。 有时称为关系的 "子级"。例如下面的 Post 类
  • 外键: 用于存储相关实体的主体键值的依赖实体中的属性。例如下面 Post.BlogId
  • 导航属性: 在主体和/或从属实体上定义的属性,该属性引用相关实体。
    • 集合导航属性: 一个导航属性,其中包含对多个子实体的引用。 例如 Blog.Posts
    • 引用导航属性: 保存对单个子实体的引用的导航属性。 例如 Post.Blog
    • 反向导航属性: 讨论特定导航属性时,此术语是指关系另一端的导航属性。

    Post.Blog 是 Blog.Posts 的反向导航属性(反之亦然)

  • 自引用关系: 依赖关系和主体实体类型相同的关系。
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; }
}

关系

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

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

  • 完全定义关系
  • 单个导航属性

完全定义关系

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

  • 如果在两个类型之间找到一对导航属性,则这些属性将配置为同一关系的反向导航属性
  • 如果依赖实体包含名称与下面其中一种模式相匹配的属性,则该属性将被配置为外键
    • <navigation property name><principal key property name>, 导航属性名称+主实体主键名称,例如 XBlogBlogId, XBlog 为导航属性名称
    • <navigation property name>Id, 导航属性名称+Id,例如 XBlogId
    • <principal entity name><principal key property name>, 主实体名称+主实体主键名称,例如 BlogBlogId
    • <principal entity name>Id, 主实体名称+Id,例如 BlogId

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

  • <navigation property name><principal key property name> ( 导航属性名称+主表主键名称) 或
  • <principal entity name><principal key property name> ( 主体类名称+主表主键名称)

单个导航属性

  • 包含一个导航属性(无反向导航,没有外键属性) 或者

例如, 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. 一个表存在对另一个表的多个关系
  • HasOne,WithOne 用于引用导航属性
  • HasMany,WithMany 用于集合导航属性
  • HasOne/WithMany 定义了一对(一对多)反向导航属性
  • HasMany/WithOne 定义了一对(一对多)反向导航属性
  • HasOne/WithOne 定义了一对(一对一)反向导航属性
  • 以上均返回 CollectionNavigationBuilder<TEntity, TRelatedEntity> (导航的构建类)
  • WIthMay , WithOne 定义在类中 CollectionNavigationBuilder<TEntity, TRelatedEntity>, 返回如下的实例

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();

相关文章

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

    关系 提纲: 比较多 关系\导航属性\自引用关系 每一个关系都会在相关实体中建立一个外键 FluentApi 的作...

  • Redis--概述和常用命令

    关系型数据库(SQL):Mysql,oracle 特点:数据和数据之间、表和字段之间,表和表之间是存在关系的。 优...

  • 初识mongodb

    MongoDB 关系型数据库和费关系型数据库 关系型数据库,表和表之间有关系(外键) 非关系型数据,表盒表之间没关...

  • 关系型数据库和非关系型数据库

    关系型数据库 关系 的个人理解:关系就是表内数据之间的、表之间的关系。表内数据是严格的对应关系,字段缺一不可,值缺...

  • 2019-07-08 关系型数据库与非关系型数据库

    关系型数据库 关系的个人理解:关系就是表内数据之间的、表之间的关系。表内数据是严格的对应关系,字段缺一不可,值缺一...

  • 【Java中级】9.0 SSH之Hibernate框架(六)——

    1.0 数据库表与表之间的关系 数据库表与表之间的关系 1.1 一对多关系 什么样关系属于一对多?一个部门对应多个...

  • 图解SQL联结:交叉联结

    1.什么是联结? 表和表之间是通过列产生关系的,这在SQL里叫做联结。联结(join):是通过表和表之间的关系将两...

  • 关系型数据库的几种设计范式(1NF 2NF 3NF BCNF 4

    关系型数据库可以看做“有多个表,表内的数据之间、表与表之间存在关系”的数据库,每个表都由行列组成,列又称作字段、域...

  • hibernate表与表之间的关系

    1、表与表之间的关系 一对一 (默认主键关联)首先在实体中描述实体与实体之间的关系,然后在映射文件中描述两个实体...

  • 表、用户、表空间之间的关系

    1、表空间是仓库,表用户是商家,表是商品 2、一个商品只能属于一个商家,也只能放入一个仓库中 3、商家可以有多个仓...

网友评论

      本文标题:2020-03-30 17:50 表之间的关系

      本文链接:https://www.haomeiwen.com/subject/tsavuhtx.html