EFCodeFirst关系映射约定

EFCodeFirst关系映射约定

默认多重关系的一些约定规则:
1.一对多关系
两个类中分别包含一个引用和一个集合属性。
两个类中一个类包含另一个类的引用属性。
两个类中一个类包含另一个类的集合属性。
2.多对多关系
两个类分别包含对方的一个集合属性。
3.一对一关系
两个类分别包含对方的一个引用属性。

1.外键列名默认约定

3种外键列名的约定方式是:

  • [Target Type Key Name],[目标类型的键名]
  • [Target Type Name] + [Target Type Key Name],[目标类型名称]+[目标类型键名称]
  • [Navigation Property Name] + [Target Type Key Name],[引用属性名称]+[目标类型键名称]

3种不同的外键名称命名之间存在优先级:

[目标类型的键名] > [引用属性名称]+[目标类型键名称] > [目标类型名称]+[目标类型键名称]。

1.[目标类型的键名]

  • 两个类中分别包含一个引用和一个集合属性的一对多种。
  • 启用级联删除功能。

2.[目标类型名称]+[目标类型键名称]

  • 两个类中一个类包含另一个类的集合属性。

3.[引用属性名称]+[目标类型键名称]

2.一对多关系

修改外键命名约定,自定义外键列名

Data Annotations方式

  1. public int CatID { get; set; } 
  2. [ForeignKey("CatID")] 
  3. public virtual Category Category { get; set; } 
  4. //或者 
  5. [ForeignKey("Category")] 
  6. public int CatID { get; set; } 
  7. public virtual Category Category { get; set; } 

Fluent API方式

  • 两个实体类之间的关系,可以两个类中均添加关系映射配置,也可以只对其中任意一个实体类添加关系映射配置。
  • 建议将实体类之间关系映射配置在包含外键的类中
  1. modelBuilder.Entity<Product>() 
  2. .HasRequired(t => t.Category) 
  3. .WithMany(t => t.Products) 
  4. .HasForeignKey(d => d.CatID); 
  • 一对多关系关系生成的外键引用约束默认是有级联删除的,可以通过以下方式禁用Category与Product之间的级联删除。
  1. protected override void OnModelCreating(DbModelBuilder modelBuilder) 
  2. { 
  3. modelBuilder.Entity<Product>() 
  4. .HasRequired(t => t.Category) 
  5. .WithMany(t => t.Products) 
  6. .HasForeignKey(d => d.CatID) 
  7. .WillCascadeOnDelete(false); 
  8. } 
  9. //也可以在Entity Framework Code First生成的全部表中都统一设置禁用一对多级联删除。 
  10. protected override void OnModelCreating(DbModelBuilder modelBuilder) 
  11. { 
  12. modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 
  13. } 
  • 可以支持外键列名自定义的,但在实际的项目中,更多的外键列名称还是与所引用表的主键列名相同。

3.一对一关系

  • 两个表均有各自的主键,但要看哪个表的主键同时作为外键引用另一个表的主键。

Data Annotations方式

UserProfile表中的主键ProfileID同时也作为外键引用User表中的主键UserID。
User为主表

  1. public partial class User 
  2. { 
  3. [Key] 
  4. public int UserID { get; set; } 
  5. public string UserName { get; set; } 
  6. public string Password { get; set; } 
  7. public Nullable<bool> IsValid { get; set; } 
  8.  
  9. public virtual UserProfile UserProfile { get; set; } 
  10. } 
  11.  
  12. ------------------------------------------------------------------------------------------ 
  13. public partial class UserProfile 
  14. { 
  15. [Key] 
  16. [ForeignKey("User")] 
  17. public int ProfileID { get; set; } 
  18. public string Name { get; set; } 
  19. public Nullable<bool> Sex { get; set; } 
  20. public Nullable<DateTime> Birthday { get; set; } 
  21. public string Email { get; set; } 
  22. public string Telephone { get; set; } 
  23. public string Mobilephone { get; set; } 
  24. public string Address { get; set; } 
  25. public Nullable<DateTime> CreateDate { get; set; } 
  26.  
  27. public virtual User User { get; set; } 
  28. } 

表User主键UserID将同时作为外键引用UserProfile表的主键ProfileID。
UserProfile为主表

  1. public partial class User 
  2. { 
  3. [Key] 
  4. [ForeignKey("UserProfile")] 
  5. public int UserID { get; set; } 
  6. public string UserName { get; set; } 
  7. public string Password { get; set; } 
  8. public Nullable<bool> IsValid { get; set; } 
  9.  
  10. public virtual UserProfile UserProfile { get; set; } 
  11. } 
  12.  
  13. ------------------------------------------------------------------------------------------ 
  14. public partial class UserProfile 
  15. { 
  16. [Key] 
  17. public int ProfileID { get; set; } 
  18. public string Name { get; set; } 
  19. public Nullable<bool> Sex { get; set; } 
  20. public Nullable<DateTime> Birthday { get; set; } 
  21. public string Email { get; set; } 
  22. public string Telephone { get; set; } 
  23. public string Mobilephone { get; set; } 
  24. public string Address { get; set; } 
  25. public Nullable<DateTime> CreateDate { get; set; } 
  26.  
  27. public virtual User User { get; set; } 
  28. } 

Fluent API方式

UserProfile表中的主键ProfileID同时也作为外键引用User表中的主键UserID。
User为主表

  1. public partial class User 
  2. { 
  3. public int UserID { get; set; } 
  4. public string UserName { get; set; } 
  5. public string Password { get; set; } 
  6. public Nullable<bool> IsValid { get; set; } 
  7.  
  8. public virtual UserProfile UserProfile { get; set; } 
  9. } 
  10. ------------------------------------------------------------------------------------------ 
  11. public class UserMap : EntityTypeConfiguration<User> 
  12. { 
  13. public UserMap() 
  14. { 
  15. // Primary Key 
  16. this.HasKey(t => t.UserID); 
  17.  
  18. // Properties 
  19. this.Property(t => t.UserName) 
  20. .HasMaxLength(50); 
  21.  
  22. this.Property(t => t.Password) 
  23. .HasMaxLength(100); 
  24.  
  25. // Table & Column Mappings 
  26. this.ToTable("User"); 
  27. this.Property(t => t.UserID).HasColumnName("UserID"); 
  28. this.Property(t => t.UserName).HasColumnName("UserName"); 
  29. this.Property(t => t.Password).HasColumnName("Password"); 
  30. this.Property(t => t.IsValid).HasColumnName("IsValid"); 
  31. } 
  32. } 
  33. ------------------------------------------------------------------------------------------  
  34. public partial class UserProfile 
  35. { 
  36. public int UserID { get; set; } 
  37. public string Name { get; set; } 
  38. public Nullable<bool> Sex { get; set; } 
  39. public Nullable<DateTime> Birthday { get; set; } 
  40. public string Email { get; set; } 
  41. public string Telephone { get; set; } 
  42. public string Mobilephone { get; set; } 
  43. public string Address { get; set; } 
  44. public Nullable<DateTime> CreateDate { get; set; } 
  45.  
  46. public virtual User User { get; set; } 
  47. } 
  48. ------------------------------------------------------------------------------------------  
  49. public class UserProfileMap : EntityTypeConfiguration<UserProfile> 
  50. { 
  51. public UserProfileMap() 
  52. { 
  53. // Primary Key 
  54. this.HasKey(t => t.UserID); 
  55.  
  56. // Properties 
  57. this.Property(t => t.UserID) 
  58. .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 
  59.  
  60. this.Property(t => t.Name) 
  61. .IsRequired() 
  62. .HasMaxLength(50); 
  63.  
  64. this.Property(t => t.Email) 
  65. .IsRequired() 
  66. .HasMaxLength(100); 
  67.  
  68. this.Property(t => t.Telephone) 
  69. .HasMaxLength(50); 
  70.  
  71. this.Property(t => t.Mobilephone) 
  72. .HasMaxLength(20); 
  73.  
  74. this.Property(t => t.Address) 
  75. .HasMaxLength(200); 
  76.  
  77. // Table & Column Mappings 
  78. this.ToTable("UserProfile"); 
  79. this.Property(t => t.UserID).HasColumnName("UserID"); 
  80. this.Property(t => t.Name).HasColumnName("Name"); 
  81. this.Property(t => t.Sex).HasColumnName("Sex"); 
  82. this.Property(t => t.Birthday).HasColumnName("Birthday"); 
  83. this.Property(t => t.Email).HasColumnName("Email"); 
  84. this.Property(t => t.Telephone).HasColumnName("Telephone"); 
  85. this.Property(t => t.Mobilephone).HasColumnName("Mobilephone"); 
  86. this.Property(t => t.Address).HasColumnName("Address"); 
  87. this.Property(t => t.CreateDate).HasColumnName("CreateDate"); 
  88.  
  89. // Relationships 
  90. this.HasRequired(t => t.User) 
  91. .WithRequiredDependent(t => t.UserProfile); 
  92. } 
  93. } 

表User主键UserID将同时作为外键引用UserProfile表的主键ProfileID。
UserProfile为主表

  1. public class UserProfileMap : EntityTypeConfiguration<UserProfile> 
  2. { 
  3. public UserProfileMap() 
  4. { 
  5. // Primary Key 
  6. this.HasKey(t => t.UserID); 
  7.  
  8. // Properties 
  9. this.Property(t => t.UserID) 
  10. .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 
  11.  
  12. this.Property(t => t.Name) 
  13. .IsRequired() 
  14. .HasMaxLength(50); 
  15.  
  16. this.Property(t => t.Email) 
  17. .IsRequired() 
  18. .HasMaxLength(100); 
  19.  
  20. this.Property(t => t.Telephone) 
  21. .HasMaxLength(50); 
  22.  
  23. this.Property(t => t.Mobilephone) 
  24. .HasMaxLength(20); 
  25.  
  26. this.Property(t => t.Address) 
  27. .HasMaxLength(200); 
  28.  
  29. // Table & Column Mappings 
  30. this.ToTable("UserProfile"); 
  31. this.Property(t => t.UserID).HasColumnName("UserID"); 
  32. this.Property(t => t.Name).HasColumnName("Name"); 
  33. this.Property(t => t.Sex).HasColumnName("Sex"); 
  34. this.Property(t => t.Birthday).HasColumnName("Birthday"); 
  35. this.Property(t => t.Email).HasColumnName("Email"); 
  36. this.Property(t => t.Telephone).HasColumnName("Telephone"); 
  37. this.Property(t => t.Mobilephone).HasColumnName("Mobilephone"); 
  38. this.Property(t => t.Address).HasColumnName("Address"); 
  39. this.Property(t => t.CreateDate).HasColumnName("CreateDate"); 
  40.  
  41. // Relationships 
  42. this.HasRequired(t => t.User) 
  43. .WithRequiredPrincipal(t => t.UserProfile); 
  44. } 
  45. } 

4.多对多关系

  • 除了生成实体类定义的属性表之外,还会生成一个中间表。用于体现两个实体表之间的多对多的关系。
  1. public partial class User 
  2. { 
  3. public int UserID { get; set; } 
  4. public string UserName { get; set; } 
  5. public string Password { get; set; } 
  6. public Nullable<bool> IsValid { get; set; } 
  7.  
  8. public virtual ICollection<Role> Roles { get; set; } 
  9. } 
  10.  
  11. public partial class Role 
  12. { 
  13. public Role() 
  14. { 
  15. this.Users = new List<User>(); 
  16. } 
  17.  
  18. public int RoleID { get; set; } 
  19. public string RoleName { get; set; } 
  20.  
  21. public virtual ICollection<User> Users { get; set; } 
  22. } 
  • 默认启用多对多的数据级联删除
  1.  
  2. protected override void OnModelCreating(DbModelBuilder modelBuilder) 
  3. { 
  4. // 禁用多对多关系表的级联删除 
  5. modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 
  6. } 
  7.  

Fluent API方式

  1. public partial class User 
  2. { 
  3. public int UserID { get; set; } 
  4. public string UserName { get; set; } 
  5. public string Password { get; set; } 
  6. public Nullable<bool> IsValid { get; set; } 
  7.  
  8. public virtual ICollection<Role> Roles { get; set; } 
  9. } 
  10. --------------------------------------------------------------------- 
  11. public class UserMap : EntityTypeConfiguration<User> 
  12. { 
  13. public UserMap() 
  14. { 
  15. // Primary Key 
  16. this.HasKey(t => t.UserID); 
  17.  
  18. // Properties 
  19. this.Property(t => t.UserName) 
  20. .HasMaxLength(50); 
  21.  
  22. this.Property(t => t.Password) 
  23. .HasMaxLength(100); 
  24.  
  25. // Table & Column Mappings 
  26. this.ToTable("User"); 
  27. this.Property(t => t.UserID).HasColumnName("UserID"); 
  28. this.Property(t => t.UserName).HasColumnName("UserName"); 
  29. this.Property(t => t.Password).HasColumnName("Password"); 
  30. this.Property(t => t.IsValid).HasColumnName("IsValid"); 
  31. } 
  32. } 
  33. ---------------------------------------------------------------------------- 
  34. public partial class Role 
  35. { 
  36. public int RoleID { get; set; } 
  37. public string RoleName { get; set; } 
  38.  
  39. public virtual ICollection<User> Users { get; set; } 
  40. } 
  41. ----------------------------------------------------------------------------- 
  42. public class RoleMap : EntityTypeConfiguration<Role> 
  43. { 
  44. public RoleMap() 
  45. { 
  46. // Primary Key 
  47. this.HasKey(t => t.RoleID); 
  48.  
  49. // Properties 
  50. this.Property(t => t.RoleName) 
  51. .HasMaxLength(50); 
  52.  
  53. // Table & Column Mappings 
  54. this.ToTable("Role"); 
  55. this.Property(t => t.RoleID).HasColumnName("RoleID"); 
  56. this.Property(t => t.RoleName).HasColumnName("RoleName"); 
  57.  
  58. // Relationships 
  59. this.HasMany(t => t.Users) 
  60. .WithMany(t => t.Roles) 
  61. .Map(m => 
  62. { 
  63. m.ToTable("UserRole"); 
  64. m.MapLeftKey("RoleID"); 
  65. m.MapRightKey("UserID"); 
  66. }); 
  67. } 
  68. } 
  69.  

5.一对多自反关系

Fluent API方式

  1. public class Category 
  2. { 
  3. public int CategoryID { get; set; } 
  4. public int CategoryNo { get; set; } 
  5. public string CategoryName { get; set; } 
  6. public Nullable<int> ParentID { get; set; } 
  7. public virtual Category Parent { get; set; } 
  8. public virtual ICollection<Category> Children { get; set; } 
  9. } 
  10. --------------------------------------------------------------------- 
  11. public class CategoryMap : EntityTypeConfiguration<Category> 
  12. { 
  13. public CategoryMap() 
  14. { 
  15. // Primary Key 
  16. this.HasKey(t => t.CategoryID); 
  17.  
  18. // Properties 
  19. this.Property(t => t.CategoryName) 
  20. .IsRequired() 
  21. .HasMaxLength(50); 
  22.  
  23. // Table & Column Mappings 
  24. this.ToTable("Category"); 
  25. this.Property(t => t.CategoryID).HasColumnName("CategoryID"); 
  26. this.Property(t => t.CategoryNo).HasColumnName("CategoryNo"); 
  27. this.Property(t => t.CategoryName).HasColumnName("CategoryName"); 
  28. this.Property(t => t.ParentID).HasColumnName("ParentID"); 
  29.  
  30. // Relationships 
  31. this.HasOptional(t => t.Parent) 
  32. .WithMany(t => t.Children) 
  33. .HasForeignKey(d => d.ParentID); 
  34. } 
  35. } 

6.多对多自反关系

Fluent API方式

  1. /// <summary> 
  2. /// Family表多对多自反关系 
  3. /// </summary> 
  4. public partial class Family 
  5. { 
  6. public Family() 
  7. { 
  8. this.Parents = new List<Family>(); 
  9. this.Children = new List<Family>(); 
  10. } 
  11.  
  12. public int FamilyID { get; set; } 
  13. public string Name { get; set; } 
  14. public Nullable<bool> Sex { get; set; } 
  15. public Nullable<System.DateTime> Birthday { get; set; } 
  16. public virtual ICollection<Family> Parents { get; set; } 
  17. public virtual ICollection<Family> Children { get; set; } 
  18. } 
  19. --------------------------------------------------------------------- 
  20. public class FamilyMap : EntityTypeConfiguration<Family> 
  21. { 
  22. public FamilyMap() 
  23. { 
  24. // Primary Key 
  25. this.HasKey(t => t.FamilyID); 
  26.  
  27. // Properties 
  28. this.Property(t => t.Name) 
  29. .HasMaxLength(50); 
  30.  
  31. // Table & Column Mappings 
  32. this.ToTable("Family"); 
  33. this.Property(t => t.FamilyID).HasColumnName("FamilyID"); 
  34. this.Property(t => t.Name).HasColumnName("Name"); 
  35. this.Property(t => t.Sex).HasColumnName("Sex"); 
  36. this.Property(t => t.Birthday).HasColumnName("Birthday"); 
  37.  
  38. // Relationships 
  39. this.HasMany(t => t.Parents) 
  40. .WithMany(t => t.Children) 
  41. .Map(m => 
  42. { 
  43. m.ToTable("FamilyRelationship"); 
  44. m.MapLeftKey("ParentID"); 
  45. m.MapRightKey("ChildID"); 
  46. }); 
  47. } 
  48. } 
posted @ 2017-06-21 18:08  明明.如月  阅读(496)  评论(0)    收藏  举报