如何将Entity Framework配置关系转换为长尾关键词?

2026-03-31 10:041阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2099个文字,预计阅读时间需要9分钟。

如何将Entity Framework配置关系转换为长尾关键词?

目录

一、Has方法与With方法

1.Has方法

2.With方法

二、一对一关系

1.DataAnnotations方式

2.Fluent API方式(1):0..1关系

3.Fluent API方式(2):1..1关系

三、一对多关系

1.DataAnnotations方式

目录
  • 一、Has方法与With方法
    • 1、Has方法:
    • 2、With方法:
  • 二、一对一关系:
    • 1、DataAnnotations数据标注的方式
    • 2、Fluent API方式
      • (1)1:0..1关系
      • (2)1:1 关系
  • 三、一对多关系:
    • 1、DataAnnotations方式
      • 2、更改外键的nullable属性和外键的名字
        • 1、使用Data Annotations指定外键:
        • 2、用Fluent API指定外键:
      • 3、对同一实体多个引用的情况
        • 4、级联删除
        • 四、多对多关系
          • 指定表名

          一、Has方法与With方法

          如:A类必须包含B类一个不为null的实例,而B类可选择时候包含A类一个实例。

          A.HasRequired(a => a.B).WithOptional(b => b.A);

          1、Has方法:

          • HasOptional:前者(A)可以包含后者(B)一个实例或者为null
          • HasRequired:前者必须包含后者一个不为null的实例
          • HasMany:前者包含后者实例的集合

          2、With方法:

          • WithOptional:后者(B)可以包含前者(A)一个实例或者null
          • WithRequired:后者必须包含前者一个不为null的实例
          • WithMany:后者包含前者实例的集合

          二、一对一关系:

          两个类中先都要配置相应的引用属性

          1、DataAnnotations数据标注的方式

          用到ForeignKey外键标注。

          public class Person { public int PersonId { get; set; } public int SocialSecurityNumber { get; set; } public string FirstName { get; set; } public string LastName { get; set; } 1675130874 public byte[] RowVersion { get; set; } public PersonPhoto Photo { get; set; } } public class PersonPhoto { [Key, ForeignKey("PhotoOf")] //注意:PersonPhoto表中的PersonId既是外键也必须是主键 public int PersonId { get; set; } public byte[] Photo { get; set; } public string Caption { get; set; } public Person PhotoOf { get; set; } }

          2、Fluent API方式

          (1)1:0..1关系

          PersonPhoto必须属于一个Person,但是Person不一定有PersonPhoto, 此种情况下Person是一定存在的,所以它是主从关系主的一方。

          modelBuilder.Entity<Person>().HasOptional(t => t.Photo).WithRequired(t => t.PhotoOf); modelBuilder.Entity<PersonPhoto>().HasRequired(p => p.PhotoOf).WithOptional(p => p.Photo);

          (2)1:1 关系

          PersonPhoto必须属于一个Person,Person也必须有PersonPhoto。

          modelBuilder.Entity<Person>().HasRequired(p => p.Photo ).WithRequiredPrincipal(); modelBuilder.Entity<PersonPhoto>().HasRequired(t => t.PhotoOf).WithRequiredDependent(t => t.Photo);

          此种情况下,两个都一定存在,要确定主从关系,需要使用WithRequiredPrincipal或WithRequiredDependent。

          • 如果你选择 WithOptionalPrincipal(当前实体为主体;目标实体为依赖对象)PersonPhoto表中有一个外键,指向Person表的主键。
          • 如果你选择 WithOptionalDependen t则相反(当前实体为依赖对象;目标实体为主体)则代表Person表中有一个外键,指向PersonPhoto表的主键,

          Person表可以没有对应的PersonPhoto表数据,但是PersonPhoto表每一条数据都必须对应一条Person表数据。意思就是人可以没有照片,但是有的照片必须属于某个人。

          三、一对多关系:

          1、DataAnnotations方式

          一对多关系很多情况下我们都不需要特意的去配置,通过一些引用属性、导航属性等检测到模型之间的关系,自动为我们生成外键。

          public class Destination {//景点类 public int DestinationId { get; set; } public string Name { get; set; } public string Country { get; set; } public string Description { get; set; } public byte[] Photo { get; set; } public List Lodgings { get; set; } } public class Lodging {//住宿类 public int LodgingId { get; set; } public string Name { get; set; } public string Owner { get; set; } public bool IsResort { get; set; } public decimal MilesFromNearestAirport { get; set; } public Destination Target { get; set; } }

          Code First观察到Lodging类中有一个对Destination的引用属性,或者Destination中又有一个集合导航属性Lodgings,因此推测出Destination与Lodging的关系是一对多关系.

          所以在生成的数据库中为自动为Lodging表生成外键:外键名:Target_DestinationId

          2、更改外键的nullable属性和外键的名字

          默认情况下,如果你的外键命名是规范的话,Code First自动会将该属性设置为外键,不再自动创建一个外键。
          规范命名是指符合:命名为如下的形式:(在这里目标类型就是Destination)

          • [目标类型的主键名]:如:DestinationId
          • [目标类型名称]+[目标类型主键名称]:如:DestinationDestinationId
          • [导航属性名称]+[目标类型主键名称]:如:TargetDestinationId

          如:DestinationId属性自动作为主键。

          public class Lodging { public int? DestinationId { get; set; } public Destination Destination { get; set; } }

          当然我们也可以自己在类中增加一个外键。

          1、使用Data Annotations指定外键:

          注意ForeignKey位置的不同,其后带的参数也不同。

          [ForeignKey("Target")] public int TarDestinationId { get; set; } public Destination Target { get; set; }

          public int TarDestinationId { get; set; } [ForeignKey("TarDestinationId")] public Destination Target { get; set; }

          2、用Fluent API指定外键:

          如果实体类没定义AccommodationId,那么可以使用Map方法直接指定外键名:.Map(s => s.MapKey("AccommodationId"))
          (1)Lodging一定归属于一个Destination,这种关系是1:n。

          modelBuilder.Entity<Destination>().HasMany(d => d.Lodgings).WithRequired(l => l.Destination).Map(l => l.MapKey("DestinationId")); modelBuilder.Entity<Lodgings>().HasRequired(l => l.Target).WithMany(d=>d.Lodgings).HasForeignKey(l => l.TarDestinationId);

          (2)Post可以单独存在,不用归属于Blog,这种关系是0..1:n。

          modelBuilder.Entity<Destination>().HasMany(d => d.Lodgings).WithOptional(l => l.Destination).Map(l => l.MapKey("DestinationId")); modelBuilder.Entity<Lodgings>().HasOptional(l => l.Target).WithMany(d => d.Lodgings).HasForeignKey(l => l.TarDestinationId);

          3、对同一实体多个引用的情况

          public class Person { public int PersonID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public List PrimaryContactFor { get; set; } public List SecondaryContactFor { get; set; } } public class Lodging { public int LodgingId { get; set; } public string Name { get; set; } public string Owner { get; set; } public bool IsResort { get; set; } public decimal MilesFromNearestAirport { get; set; } public Destination Target { get; set; } //第一联系人 public Person PrimaryContact { get; set; } //第二联系人 public Person SecondaryContact { get; set; } }

          Lodging(旅店)有两个对Person表的引用,分别是PrimaryContact与SecondaryContact,
          同时,在Person表中也有对这两个联系人的导航:PrimaryContactFor与SecondaryContactFor。

          因为在这两个表之间存在多个一对多关系,所以Code First无法处理这种情况。
          为了让Code First知道它们之间的对应关系,在这里要用到逆导航属性来解决。

          (1)使用Data Annotations:

          //第一联系人 [InverseProperty("PrimaryContactFor")] public Person PrimaryContact { get; set; } //第二联系人 [InverseProperty("SecondaryContactFor")] Person SecondaryContact { get; set; }

          (2)或使用Fluent API:

          modelBuilder.Entity<Lodging>().HasOptional(l => l.PrimaryContact).WithMany(p => p.PrimaryContactFor); modelBuilder.Entity<Lodging>().HasOptional(l=>l.SecondaryContact).WithMany(p=>p.SecondaryContactFor)).Map(p => p.MapKey("SecondaryPersonID "));;

          在生成的数据库中为自动为Lodging表生成两个外键:PrimaryContact _PersonID 和SecondaryPersonID

          如何将Entity Framework配置关系转换为长尾关键词?

          4、级联删除

          1、如果两个表之间存在一对多关系,Code First默认会开启两个表之间的级联删除功能
          数据库里可以可视化的设置不级联删除,Fluent API配置此外键关系时可以设置不级联删除:

          this.HasMany(d => d.Lodgings).WithRequired(l => l.Destination).Map(l => l.MapKey("DestinationId")) //一对多并指定外键名 .WillCascadeOnDelete(false); // 关闭级联删除

          2、也可以在上下文的OnModelCreating方法中移除这个默认约定

          modelBuilder.Conventions.Remove();

          再需要开启级联删除,则可以在FluentAPI关系映射中用. WillCascadeOnDelete(true) 单独开启

          四、多对多关系

          如果有两个类中,各自都是导航属性指向另一个类,Code First会认为这两个类之间是多对多关系,例如:

          public class Trip { public int TripId { get; set; } public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } public decimal CostUSD { get; set; } public byte[] RowVersion { get; set; } public List Activities { get; set; } } public class Activity { public int ActivityId { get; set; } [Required, MaxLength(50)] public string Name { get; set; } public List Trips { get; set; } }

          Code First生成了一张中间表ActivityTrips,将另外两张表的主键都作为外键关联到了中间表上面。
          中间表中字段的命名默认为"[目标类型名称]_[目标类型键名称]".Activity_ActivityId 和Trip_TripId
          并且也作为这个新的连接表的联合主键。

          指定表名

          如果我们想指定中间表的名称和键名称,我们可以用Fluent API来配置。

          modelBuilder.Entity<Trap>().HasMany(t => t.Activities).WithMany(a => a.Trips).Map(m => { m.ToTable("TripActivities"); m.MapLeftKey("TripIdentifier");//对应Trip的主键 m.MapRightKey("ActivityId"); }); //或者 modelBuilder<Activity>.Entity().HasMany(a => a.Trips).WithMany(t => t.Activities).Map(m => { m.ToTable("TripActivities"); m.MapLeftKey("ActivityId");//对应Activity的主键 m.MapRightKey("TripIdentifier"); });

          到此这篇关于Entity Framework配置关系的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持自由互联。

          本文共计2099个文字,预计阅读时间需要9分钟。

          如何将Entity Framework配置关系转换为长尾关键词?

          目录

          一、Has方法与With方法

          1.Has方法

          2.With方法

          二、一对一关系

          1.DataAnnotations方式

          2.Fluent API方式(1):0..1关系

          3.Fluent API方式(2):1..1关系

          三、一对多关系

          1.DataAnnotations方式

          目录
          • 一、Has方法与With方法
            • 1、Has方法:
            • 2、With方法:
          • 二、一对一关系:
            • 1、DataAnnotations数据标注的方式
            • 2、Fluent API方式
              • (1)1:0..1关系
              • (2)1:1 关系
          • 三、一对多关系:
            • 1、DataAnnotations方式
              • 2、更改外键的nullable属性和外键的名字
                • 1、使用Data Annotations指定外键:
                • 2、用Fluent API指定外键:
              • 3、对同一实体多个引用的情况
                • 4、级联删除
                • 四、多对多关系
                  • 指定表名

                  一、Has方法与With方法

                  如:A类必须包含B类一个不为null的实例,而B类可选择时候包含A类一个实例。

                  A.HasRequired(a => a.B).WithOptional(b => b.A);

                  1、Has方法:

                  • HasOptional:前者(A)可以包含后者(B)一个实例或者为null
                  • HasRequired:前者必须包含后者一个不为null的实例
                  • HasMany:前者包含后者实例的集合

                  2、With方法:

                  • WithOptional:后者(B)可以包含前者(A)一个实例或者null
                  • WithRequired:后者必须包含前者一个不为null的实例
                  • WithMany:后者包含前者实例的集合

                  二、一对一关系:

                  两个类中先都要配置相应的引用属性

                  1、DataAnnotations数据标注的方式

                  用到ForeignKey外键标注。

                  public class Person { public int PersonId { get; set; } public int SocialSecurityNumber { get; set; } public string FirstName { get; set; } public string LastName { get; set; } 1675130874 public byte[] RowVersion { get; set; } public PersonPhoto Photo { get; set; } } public class PersonPhoto { [Key, ForeignKey("PhotoOf")] //注意:PersonPhoto表中的PersonId既是外键也必须是主键 public int PersonId { get; set; } public byte[] Photo { get; set; } public string Caption { get; set; } public Person PhotoOf { get; set; } }

                  2、Fluent API方式

                  (1)1:0..1关系

                  PersonPhoto必须属于一个Person,但是Person不一定有PersonPhoto, 此种情况下Person是一定存在的,所以它是主从关系主的一方。

                  modelBuilder.Entity<Person>().HasOptional(t => t.Photo).WithRequired(t => t.PhotoOf); modelBuilder.Entity<PersonPhoto>().HasRequired(p => p.PhotoOf).WithOptional(p => p.Photo);

                  (2)1:1 关系

                  PersonPhoto必须属于一个Person,Person也必须有PersonPhoto。

                  modelBuilder.Entity<Person>().HasRequired(p => p.Photo ).WithRequiredPrincipal(); modelBuilder.Entity<PersonPhoto>().HasRequired(t => t.PhotoOf).WithRequiredDependent(t => t.Photo);

                  此种情况下,两个都一定存在,要确定主从关系,需要使用WithRequiredPrincipal或WithRequiredDependent。

                  • 如果你选择 WithOptionalPrincipal(当前实体为主体;目标实体为依赖对象)PersonPhoto表中有一个外键,指向Person表的主键。
                  • 如果你选择 WithOptionalDependen t则相反(当前实体为依赖对象;目标实体为主体)则代表Person表中有一个外键,指向PersonPhoto表的主键,

                  Person表可以没有对应的PersonPhoto表数据,但是PersonPhoto表每一条数据都必须对应一条Person表数据。意思就是人可以没有照片,但是有的照片必须属于某个人。

                  三、一对多关系:

                  1、DataAnnotations方式

                  一对多关系很多情况下我们都不需要特意的去配置,通过一些引用属性、导航属性等检测到模型之间的关系,自动为我们生成外键。

                  public class Destination {//景点类 public int DestinationId { get; set; } public string Name { get; set; } public string Country { get; set; } public string Description { get; set; } public byte[] Photo { get; set; } public List Lodgings { get; set; } } public class Lodging {//住宿类 public int LodgingId { get; set; } public string Name { get; set; } public string Owner { get; set; } public bool IsResort { get; set; } public decimal MilesFromNearestAirport { get; set; } public Destination Target { get; set; } }

                  Code First观察到Lodging类中有一个对Destination的引用属性,或者Destination中又有一个集合导航属性Lodgings,因此推测出Destination与Lodging的关系是一对多关系.

                  所以在生成的数据库中为自动为Lodging表生成外键:外键名:Target_DestinationId

                  2、更改外键的nullable属性和外键的名字

                  默认情况下,如果你的外键命名是规范的话,Code First自动会将该属性设置为外键,不再自动创建一个外键。
                  规范命名是指符合:命名为如下的形式:(在这里目标类型就是Destination)

                  • [目标类型的主键名]:如:DestinationId
                  • [目标类型名称]+[目标类型主键名称]:如:DestinationDestinationId
                  • [导航属性名称]+[目标类型主键名称]:如:TargetDestinationId

                  如:DestinationId属性自动作为主键。

                  public class Lodging { public int? DestinationId { get; set; } public Destination Destination { get; set; } }

                  当然我们也可以自己在类中增加一个外键。

                  1、使用Data Annotations指定外键:

                  注意ForeignKey位置的不同,其后带的参数也不同。

                  [ForeignKey("Target")] public int TarDestinationId { get; set; } public Destination Target { get; set; }

                  public int TarDestinationId { get; set; } [ForeignKey("TarDestinationId")] public Destination Target { get; set; }

                  2、用Fluent API指定外键:

                  如果实体类没定义AccommodationId,那么可以使用Map方法直接指定外键名:.Map(s => s.MapKey("AccommodationId"))
                  (1)Lodging一定归属于一个Destination,这种关系是1:n。

                  modelBuilder.Entity<Destination>().HasMany(d => d.Lodgings).WithRequired(l => l.Destination).Map(l => l.MapKey("DestinationId")); modelBuilder.Entity<Lodgings>().HasRequired(l => l.Target).WithMany(d=>d.Lodgings).HasForeignKey(l => l.TarDestinationId);

                  (2)Post可以单独存在,不用归属于Blog,这种关系是0..1:n。

                  modelBuilder.Entity<Destination>().HasMany(d => d.Lodgings).WithOptional(l => l.Destination).Map(l => l.MapKey("DestinationId")); modelBuilder.Entity<Lodgings>().HasOptional(l => l.Target).WithMany(d => d.Lodgings).HasForeignKey(l => l.TarDestinationId);

                  3、对同一实体多个引用的情况

                  public class Person { public int PersonID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public List PrimaryContactFor { get; set; } public List SecondaryContactFor { get; set; } } public class Lodging { public int LodgingId { get; set; } public string Name { get; set; } public string Owner { get; set; } public bool IsResort { get; set; } public decimal MilesFromNearestAirport { get; set; } public Destination Target { get; set; } //第一联系人 public Person PrimaryContact { get; set; } //第二联系人 public Person SecondaryContact { get; set; } }

                  Lodging(旅店)有两个对Person表的引用,分别是PrimaryContact与SecondaryContact,
                  同时,在Person表中也有对这两个联系人的导航:PrimaryContactFor与SecondaryContactFor。

                  因为在这两个表之间存在多个一对多关系,所以Code First无法处理这种情况。
                  为了让Code First知道它们之间的对应关系,在这里要用到逆导航属性来解决。

                  (1)使用Data Annotations:

                  //第一联系人 [InverseProperty("PrimaryContactFor")] public Person PrimaryContact { get; set; } //第二联系人 [InverseProperty("SecondaryContactFor")] Person SecondaryContact { get; set; }

                  (2)或使用Fluent API:

                  modelBuilder.Entity<Lodging>().HasOptional(l => l.PrimaryContact).WithMany(p => p.PrimaryContactFor); modelBuilder.Entity<Lodging>().HasOptional(l=>l.SecondaryContact).WithMany(p=>p.SecondaryContactFor)).Map(p => p.MapKey("SecondaryPersonID "));;

                  在生成的数据库中为自动为Lodging表生成两个外键:PrimaryContact _PersonID 和SecondaryPersonID

                  如何将Entity Framework配置关系转换为长尾关键词?

                  4、级联删除

                  1、如果两个表之间存在一对多关系,Code First默认会开启两个表之间的级联删除功能
                  数据库里可以可视化的设置不级联删除,Fluent API配置此外键关系时可以设置不级联删除:

                  this.HasMany(d => d.Lodgings).WithRequired(l => l.Destination).Map(l => l.MapKey("DestinationId")) //一对多并指定外键名 .WillCascadeOnDelete(false); // 关闭级联删除

                  2、也可以在上下文的OnModelCreating方法中移除这个默认约定

                  modelBuilder.Conventions.Remove();

                  再需要开启级联删除,则可以在FluentAPI关系映射中用. WillCascadeOnDelete(true) 单独开启

                  四、多对多关系

                  如果有两个类中,各自都是导航属性指向另一个类,Code First会认为这两个类之间是多对多关系,例如:

                  public class Trip { public int TripId { get; set; } public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } public decimal CostUSD { get; set; } public byte[] RowVersion { get; set; } public List Activities { get; set; } } public class Activity { public int ActivityId { get; set; } [Required, MaxLength(50)] public string Name { get; set; } public List Trips { get; set; } }

                  Code First生成了一张中间表ActivityTrips,将另外两张表的主键都作为外键关联到了中间表上面。
                  中间表中字段的命名默认为"[目标类型名称]_[目标类型键名称]".Activity_ActivityId 和Trip_TripId
                  并且也作为这个新的连接表的联合主键。

                  指定表名

                  如果我们想指定中间表的名称和键名称,我们可以用Fluent API来配置。

                  modelBuilder.Entity<Trap>().HasMany(t => t.Activities).WithMany(a => a.Trips).Map(m => { m.ToTable("TripActivities"); m.MapLeftKey("TripIdentifier");//对应Trip的主键 m.MapRightKey("ActivityId"); }); //或者 modelBuilder<Activity>.Entity().HasMany(a => a.Trips).WithMany(t => t.Activities).Map(m => { m.ToTable("TripActivities"); m.MapLeftKey("ActivityId");//对应Activity的主键 m.MapRightKey("TripIdentifier"); });

                  到此这篇关于Entity Framework配置关系的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持自由互联。