Code First 配置外键 一对多 多对多

配置外键

一:导航属性

外键字段在模型中没有,没法自己去控制联和查询只能使用导航属性

  1. //子表
  2. namespace Model
  3. {
  4. [Table("UserInfo")]
  5. public class UserInfo
  6. {
  7. [Key]
  8. public int id { get; set; }
  9. [Required]
  10. public string UserName { get; set; }
  11. [StringLength(32), Required]
  12. public string Number { get; set; }
  13. //1外键添加
  14. public virtual Userparent userparent { get; set; }
  15. }
  16. }
  17. //主表
  18. namespace Model
  19. {
  20. public class Userparent
  21. {
  22. public int Id { get; set; }
  23. public string Father { get; set; }
  24. public string Mother { get; set; }
  25. public virtual List<UserInfo> users { get; set; }
  26. }
  27. }

二:导航属性+自定义属性

  1. //[Table("UserInfo")]
  2. public class UserInfo
  3. {
  4. [Key]
  5. public int id { get; set; }
  6. [Required]
  7. public string UserName { get; set; }
  8. [StringLength(32), Required]
  9. public string Number { get; set; }
  10. //1外键
  11. [ForeignKey("userparent")]
  12. public int UserparentId { get; set; }
  13. public virtual Userparent userparent { get; set; }
  14. }
  1. [Table("UserInfo")]
  2. public class UserInfo
  3. {
  4. [Key]
  5. public int id { get; set; }
  6. [Required]
  7. public string UserName { get; set; }
  8. [StringLength(32), Required]
  9. public string Number { get; set; }
  10. //2外键
  11. public int UserparentId { get; set; }
  12. [ForeignKey("UserparentId")]
  13. public virtual Userparent userparent { get; set; }
  14. }

三:在上下文对象中重写模型创建,使用fluent api

级联删除
Ef code first默认开启级联删除,从你删除的表,当做主表,把相关的数据全部删除。

  1. //方法一对多来配置
  2. //虚方法
  3. // 建议用法:在需要的表加.WillCascadeOnDelete(false); 如果用全局可能会造成数据不小心全部删除
  4. protected override void OnModelCreating(DbModelBuilder modelBuilder)
  5. {
  6. //一对多来配置后面不加.WillCascadeOnDelete(false)默认开启联表删除
  7. modelBuilder.Entity<UserInfo>().HasRequired(a => a.userparent).WithMany(a => a.users).HasForeignKey(a => a.UserparentId);
  8. //方法多对一来配置
  9. modelBuilder.Entity<多的对象名称>().HasMany(a => a.users 多的对象需配置的链接字段 ).WithRequired(a => a.userparent 少的对象须配置的链接字段).HasForeignKey(a => a.UserparentId 少的字段最终确认链接字段 );
  10. modelBuilder.Entity<Userparent>().HasMany(a => a.users).WithRequired(a => a.userparent).HasForeignKey(a => a.UserparentId).WillCascadeOnDelete(false);
  11. //如果关闭级联删除在后面加.WillCascadeOnDelete(false)
  12. //fales表示的是关闭联级删除
  13. //true表示的是打开
  14. //全部关闭
  15. modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
  16. //生成的表去掉自动生成的后缀名s
  17. modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
  18. //级联删除的关闭或者开启
  19. //1:只删除或者关闭某两个表的关系
  20. modelBuilder.Entity<Userparent>().HasMany(a => a.users).WithRequired(a => a.userparent).HasForeignKey(a => a.UserparentId).WillCascadeOnDelete(false);
  21. }
  22. [Table("UserInfo")]
  23. public class UserInfo
  24. {
  25. [Key]
  26. public int id { get; set; }
  27. [Required]
  28. public string UserName { get; set; }
  29. [StringLength(32), Required]
  30. public string Number { get; set; }
  31. //3利用虚方法外键
  32. public int UserparentId { get; set; }
  33. public virtual Userparent userparent { get; set; }
  34. }
  35. namespace DAL
  36. {
  37. public class ShopContext : DbContext
  38. {
  39. public ShopContext()
  40. : base("name=ShopEetities")
  41. {
  42. }
  43. //虚方法
  44. protected override void OnModelCreating(DbModelBuilder modelBuilder)
  45. {
  46. //方法一配置1的一方
  47. //modelBuilder.Entity<UserInfo>().HasRequired(a => a.userparent).WithMany(a => a.users).HasForeignKey(a => a.UserparentId);
  48. //方法二配置多的一方
  49. //modelBuilder.Entity<多的对象名称>().HasMany(a => a.users 多的对象需配置的链接字段 ).WithRequired(a => a.userparent 少的对象须配置的链接字段).HasForeignKey(a => a.UserparentId 少的字段最终确认链接字段 );
  50. modelBuilder.Entity<Userparent>().HasMany(a => a.users).WithRequired(a => a.userparent).HasForeignKey(a => a.UserparentId);
  51. }
  52. public DbSet<UserInfo> UserInfo { get; set; }
  53. public DbSet<Userparent> Userparent { get; set; }
  54. }
  55. }

配置多对多

学生 课程
1 多
多 1
多对多关系,应该有一个中间表,用于关联,关联表至少两个字段,就是两张表的id

导航属性

只需要在相关联的表增加对方的表名就可以自动生成关系如

  1. public class UserInfo
  2. {
  3. [Key]
  4. public int id { get; set; }
  5. [Required]
  6. public string UserName { get; set; }
  7. [StringLength(32), Required]
  8. public string Number { get; set; }
  9. //3利用虚方法外键
  10. public int UserparentId { get; set; }
  11. public virtual Userparent userparent { get; set; }
  12. //相关联的字段
  13. public virtual List<Sub 相关联的表名> Coress { get; set; }
  14. }
  15. public class Sub
  16. {
  17. public int Id { get; set; }
  18. public string Cores { get; set; }
  19. //相关联的字段
  20. public virtual List<UserInfo 相关联的表名> userinfos { get; set; }
  21. }

使用fluentApi

更灵活,关联表的表名,两个外键可以自己灵活控制

配置多对多

  1. //配置生成的一张新表表示关系
  2. //1.ToTable(自定义新表表名);
  3. //2.MapLeftKey(自定义用户的关联字段);
  4. //3.MapRightKey(自定义成绩关联的字段);
  5. modelBuilder.Entity<UserInfo>().HasMany(a => a.Coress).WithMany(a => a.userinfos).Map(a =>
  6. {
  7. a.ToTable("UserInfo_Sub");
  8. a.MapLeftKey("UserId");
  9. a.MapRightKey("SubId");
  10. });

自己维护
最灵活的,不仅可以自己控制表名外键名,还可以自己维护对象已经其他其他字段。
(多对多其实可以理解成两个1对多。可以拆分成两个多对多)

数据库迁移

Enable-Migrations启用数据库迁移
Enable-Migrations –EnableAutomaticMigrations 启动自动迁移
Update-Database 更新到数据库