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. modelBuilder.Entity<Product>() 
  3. .HasRequired(t => t.Category) 
  4. .WithMany(t => t.Products) 
  5. .HasForeignKey(d => d.CatID) 
  6. .WillCascadeOnDelete(false); 

  7. //也可以在Entity Framework Code First生成的全部表中都统一设置禁用一对多级联删除。 
  8. protected override void OnModelCreating(DbModelBuilder modelBuilder) 

  9. modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 

  • 可以支持外键列名自定义的,但在实际的项目中,更多的外键列名称还是与所引用表的主键列名相同。

3.一对一关系

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

Data Annotations方式

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

  1. public partial class User 

  2. [Key] 
  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 partial class UserProfile 

  12. [Key] 
  13. [ForeignKey("User")] 
  14. public int ProfileID { get; set; } 
  15. public string Name { get; set; } 
  16. public Nullable<bool> Sex { get; set; } 
  17. public Nullable<DateTime> Birthday { get; set; } 
  18. public string Email { get; set; } 
  19. public string Telephone { get; set; } 
  20. public string Mobilephone { get; set; } 
  21. public string Address { get; set; } 
  22. public Nullable<DateTime> CreateDate { get; set; } 
  23.  
  24. public virtual User User { get; set; } 

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

  1. public partial class User 

  2. [Key] 
  3. [ForeignKey("UserProfile")] 
  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. public partial class UserProfile 

  13. [Key] 
  14. public int ProfileID { get; set; } 
  15. public string Name { get; set; } 
  16. public Nullable<bool> Sex { get; set; } 
  17. public Nullable<DateTime> Birthday { get; set; } 
  18. public string Email { get; set; } 
  19. public string Telephone { get; set; } 
  20. public string Mobilephone { get; set; } 
  21. public string Address { get; set; } 
  22. public Nullable<DateTime> CreateDate { get; set; } 
  23.  
  24. public virtual User User { get; set; } 

Fluent API方式

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

  1. public partial class User 

  2. public int UserID { get; set; } 
  3. public string UserName { get; set; } 
  4. public string Password { get; set; } 
  5. public Nullable<bool> IsValid { get; set; } 
  6.  
  7. public virtual UserProfile UserProfile { get; set; } 

  8. ------------------------------------------------------------------------------------------ 
  9. public class UserMap : EntityTypeConfiguration<User

  10. public UserMap() 

  11. // Primary Key 
  12. this.HasKey(t => t.UserID); 
  13.  
  14. // Properties 
  15. this.Property(t => t.UserName) 
  16. .HasMaxLength(50); 
  17.  
  18. this.Property(t => t.Password) 
  19. .HasMaxLength(100); 
  20.  
  21. // Table & Column Mappings 
  22. this.ToTable("User"); 
  23. this.Property(t => t.UserID).HasColumnName("UserID"); 
  24. this.Property(t => t.UserName).HasColumnName("UserName"); 
  25. this.Property(t => t.Password).HasColumnName("Password"); 
  26. this.Property(t => t.IsValid).HasColumnName("IsValid"); 


  27. ------------------------------------------------------------------------------------------  
  28. public partial class UserProfile 

  29. public int UserID { get; set; } 
  30. public string Name { get; set; } 
  31. public Nullable<bool> Sex { get; set; } 
  32. public Nullable<DateTime> Birthday { get; set; } 
  33. public string Email { get; set; } 
  34. public string Telephone { get; set; } 
  35. public string Mobilephone { get; set; } 
  36. public string Address { get; set; } 
  37. public Nullable<DateTime> CreateDate { get; set; } 
  38.  
  39. public virtual User User { get; set; } 

  40. ------------------------------------------------------------------------------------------  
  41. public class UserProfileMap : EntityTypeConfiguration<UserProfile

  42. public UserProfileMap() 

  43. // Primary Key 
  44. this.HasKey(t => t.UserID); 
  45.  
  46. // Properties 
  47. this.Property(t => t.UserID) 
  48. .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 
  49.  
  50. this.Property(t => t.Name) 
  51. .IsRequired() 
  52. .HasMaxLength(50); 
  53.  
  54. this.Property(t => t.Email) 
  55. .IsRequired() 
  56. .HasMaxLength(100); 
  57.  
  58. this.Property(t => t.Telephone) 
  59. .HasMaxLength(50); 
  60.  
  61. this.Property(t => t.Mobilephone) 
  62. .HasMaxLength(20); 
  63.  
  64. this.Property(t => t.Address) 
  65. .HasMaxLength(200); 
  66.  
  67. // Table & Column Mappings 
  68. this.ToTable("UserProfile"); 
  69. this.Property(t => t.UserID).HasColumnName("UserID"); 
  70. this.Property(t => t.Name).HasColumnName("Name"); 
  71. this.Property(t => t.Sex).HasColumnName("Sex"); 
  72. this.Property(t => t.Birthday).HasColumnName("Birthday"); 
  73. this.Property(t => t.Email).HasColumnName("Email"); 
  74. this.Property(t => t.Telephone).HasColumnName("Telephone"); 
  75. this.Property(t => t.Mobilephone).HasColumnName("Mobilephone"); 
  76. this.Property(t => t.Address).HasColumnName("Address"); 
  77. this.Property(t => t.CreateDate).HasColumnName("CreateDate"); 
  78.  
  79. // Relationships 
  80. this.HasRequired(t => t.User) 
  81. .WithRequiredDependent(t => t.UserProfile); 


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

  1. public class UserProfileMap : EntityTypeConfiguration<UserProfile

  2. public UserProfileMap() 

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


4.多对多关系

  • 除了生成实体类定义的属性表之外,还会生成一个中间表。用于体现两个实体表之间的多对多的关系。
  1. public partial class User 

  2. public int UserID { get; set; } 
  3. public string UserName { get; set; } 
  4. public string Password { get; set; } 
  5. public Nullable<bool> IsValid { get; set; } 
  6.  
  7. public virtual ICollection<Role> Roles { get; set; } 

  8.  
  9. public partial class Role 

  10. public Role() 

  11. this.Users = new List<User>(); 

  12.  
  13. public int RoleID { get; set; } 
  14. public string RoleName { get; set; } 
  15.  
  16. public virtual ICollection<User> Users { get; set; } 

  • 默认启用多对多的数据级联删除
  1.  
  2. protected override void OnModelCreating(DbModelBuilder modelBuilder) 

  3. // 禁用多对多关系表的级联删除 
  4. modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 

  5.  

Fluent API方式

  1. public partial class User 

  2. public int UserID { get; set; } 
  3. public string UserName { get; set; } 
  4. public string Password { get; set; } 
  5. public Nullable<bool> IsValid { get; set; } 
  6.  
  7. public virtual ICollection<Role> Roles { get; set; } 

  8. --------------------------------------------------------------------- 
  9. public class UserMap : EntityTypeConfiguration<User

  10. public UserMap() 

  11. // Primary Key 
  12. this.HasKey(t => t.UserID); 
  13.  
  14. // Properties 
  15. this.Property(t => t.UserName) 
  16. .HasMaxLength(50); 
  17.  
  18. this.Property(t => t.Password) 
  19. .HasMaxLength(100); 
  20.  
  21. // Table & Column Mappings 
  22. this.ToTable("User"); 
  23. this.Property(t => t.UserID).HasColumnName("UserID"); 
  24. this.Property(t => t.UserName).HasColumnName("UserName"); 
  25. this.Property(t => t.Password).HasColumnName("Password"); 
  26. this.Property(t => t.IsValid).HasColumnName("IsValid"); 


  27. ---------------------------------------------------------------------------- 
  28. public partial class Role 

  29. public int RoleID { get; set; } 
  30. public string RoleName { get; set; } 
  31.  
  32. public virtual ICollection<User> Users { get; set; } 

  33. ----------------------------------------------------------------------------- 
  34. public class RoleMap : EntityTypeConfiguration<Role

  35. public RoleMap() 

  36. // Primary Key 
  37. this.HasKey(t => t.RoleID); 
  38.  
  39. // Properties 
  40. this.Property(t => t.RoleName) 
  41. .HasMaxLength(50); 
  42.  
  43. // Table & Column Mappings 
  44. this.ToTable("Role"); 
  45. this.Property(t => t.RoleID).HasColumnName("RoleID"); 
  46. this.Property(t => t.RoleName).HasColumnName("RoleName"); 
  47.  
  48. // Relationships 
  49. this.HasMany(t => t.Users) 
  50. .WithMany(t => t.Roles) 
  51. .Map(m => 

  52. m.ToTable("UserRole"); 
  53. m.MapLeftKey("RoleID"); 
  54. m.MapRightKey("UserID"); 
  55. }); 


  56.  

5.一对多自反关系

Fluent API方式

  1. public class Category 

  2. public int CategoryID { get; set; } 
  3. public int CategoryNo { get; set; } 
  4. public string CategoryName { get; set; } 
  5. public Nullable<int> ParentID { get; set; } 
  6. public virtual Category Parent { get; set; } 
  7. public virtual ICollection<Category> Children { get; set; } 

  8. --------------------------------------------------------------------- 
  9. public class CategoryMap : EntityTypeConfiguration<Category

  10. public CategoryMap() 

  11. // Primary Key 
  12. this.HasKey(t => t.CategoryID); 
  13.  
  14. // Properties 
  15. this.Property(t => t.CategoryName) 
  16. .IsRequired() 
  17. .HasMaxLength(50); 
  18.  
  19. // Table & Column Mappings 
  20. this.ToTable("Category"); 
  21. this.Property(t => t.CategoryID).HasColumnName("CategoryID"); 
  22. this.Property(t => t.CategoryNo).HasColumnName("CategoryNo"); 
  23. this.Property(t => t.CategoryName).HasColumnName("CategoryName"); 
  24. this.Property(t => t.ParentID).HasColumnName("ParentID"); 
  25.  
  26. // Relationships 
  27. this.HasOptional(t => t.Parent) 
  28. .WithMany(t => t.Children) 
  29. .HasForeignKey(d => d.ParentID); 


6.多对多自反关系

Fluent API方式

  1. /// <summary> 
  2. /// Family表多对多自反关系 
  3. /// </summary> 
  4. public partial class Family 

  5. public Family() 

  6. this.Parents = new List<Family>(); 
  7. this.Children = new List<Family>(); 

  8.  
  9. public int FamilyID { get; set; } 
  10. public string Name { get; set; } 
  11. public Nullable<bool> Sex { get; set; } 
  12. public Nullable<System.DateTime> Birthday { get; set; } 
  13. public virtual ICollection<Family> Parents { get; set; } 
  14. public virtual ICollection<Family> Children { get; set; } 

  15. --------------------------------------------------------------------- 
  16. public class FamilyMap : EntityTypeConfiguration<Family

  17. public FamilyMap() 

  18. // Primary Key 
  19. this.HasKey(t => t.FamilyID); 
  20.  
  21. // Properties 
  22. this.Property(t => t.Name) 
  23. .HasMaxLength(50); 
  24.  
  25. // Table & Column Mappings 
  26. this.ToTable("Family"); 
  27. this.Property(t => t.FamilyID).HasColumnName("FamilyID"); 
  28. this.Property(t => t.Name).HasColumnName("Name"); 
  29. this.Property(t => t.Sex).HasColumnName("Sex"); 
  30. this.Property(t => t.Birthday).HasColumnName("Birthday"); 
  31.  
  32. // Relationships 
  33. this.HasMany(t => t.Parents) 
  34. .WithMany(t => t.Children) 
  35. .Map(m => 

  36. m.ToTable("FamilyRelationship"); 
  37. m.MapLeftKey("ParentID"); 
  38. m.MapRightKey("ChildID"); 
  39. }); 


posted @ 2017-06-21 18:08  明明.如月  阅读(465)  评论(0编辑  收藏  举报