上一篇文章我们讲解了如何用 Fluent API 来配置/映射属性和类型,本文将把重点放在其是如何配置关系的。

  文中所使用代码如下

  1. public class Student
  2. {
  3. public int ID { get; set; }
  4. public string Name { get; set; }
  5. public DateTime EnrollmentDate { get; set; }
  6.  
  7. // Navigation properties
  8. public virtual Address Address { get; set; }
  9. public virtual OtherInfo OtherInfo { get; set; }
  10. public virtual ICollection<Enrollment> Enrollments { get; set; }
  11. }
  12.  
  13. public class Department
  14. {
  15. public Department()
  16. {
  17. this.Courses = new HashSet<Course>();
  18. }
  19. // Primary key
  20. public int DepartmentID { get; set; }
  21. public string Name { get; set; }
  22. public decimal Budget { get; set; }
  23. public System.DateTime StartDate { get; set; }
  24. public int? Administrator { get; set; }
  25.  
  26. // Navigation property
  27. public virtual ICollection<Course> Courses { get; private set; }
  28. }
  29.  
  30. public class Course
  31. {
  32. public int CourseID { get; set; }
  33. public string Title { get; set; }
  34. public int Credits { get; set; }
  35.  
  36. // Foreign key
  37. public int DepartmentID { get; set; }
  38. public string DepartmentName { get; set; }
  39.  
  40. public int SomeDepartmentID { get; set; }
  41.  
  42. // Navigation properties
  43. public virtual Department Department { get; set; }
  44. public virtual ICollection<Enrollment> Enrollments { get; set; }
  45. public virtual ICollection<Instructor> Instructors { get; set; }
  46. }
  47.  
  48. public class Instructor
  49. {
  50. public int InstructorID { get; set; }
  51. public string Name { get; set; }
  52. public DateTime HireDate { get; set; }
  53.  
  54. // Navigation properties
  55. public virtual ICollection<Course> Courses { get; set; }
  56. }
  57.  
  58. public class Enrollment
  59. {
  60. public int EnrollmentID { get; set; }
  61. public int CourseID { get; set; }
  62. public int StudentID { get; set; }
  63.  
  64. // Navigation property
  65. public virtual Course Course { get; set; }
  66. public virtual Student Student { get; set; }
  67. }
  68.  
  69. public class Address
  70. {
  71. public int AddressId { get; set; }
  72. public string HomeAddress { get; set; }
  73. public string LiveAddress { get; set; }
  74.  
  75. // Navigation property
  76. public virtual Student Student { get; set; }
  77. }
  78.  
  79. public class OtherInfo
  80. {
  81. public int Id { get; set; }
  82. public string HomeAddress { get; set; }
  83. public string MailAddress { get; set; }
  84. public string PhoneNumber { get; set; }
  85. public string StudentID { get; set; }
  86.  
  87. // Navigation property
  88. public virtual Student Student { get; set; }
  89. }

EntityTypeConfiguration<TEntityType>

  上面是泛型类的部分方法截图,一般我们通过 Code First Fluent API 来配置实体间的关系时都是从此泛型类的实例开始,此泛型类为我们提供了大部分的关系处理方法,如必须的 HasRequired ,可选的 HasOptional ,多个的 HasMany .

  上面所有方法(除了 HasMany, HasOptional, HasRequired )的返回值都是泛型类 EntityTypeConfiguration<TEntityType> 的实例本身,这给链式操作提供了极大地方便.

  HasRequired, HasOptional, HasMany 这三个方法的参数都是一个 lambda expression, 只不过前两个用于表示实体关系(Relationship)间的导航属性(navigation property),后一个则是导航属性的集合(Collection

  HasRequired, HasOptional, HasMany 这三个方法的返回值都是可以继续进行配置的泛型类实例,虽然名称不同,方法名也略有不同,但方法主体所体现的思想是一致的

RequiredNavigationPropertyConfiguration<TEntityType, TTargetEntityType>

OptionalNavigationPropertyConfiguration<TEntityType, TTargetEntityType>

ManyNavigationPropertyConfiguration<TEntityType, TTargetEntityType>

  三个泛型类都有类似于如下三个方法 WithRequired, WithOptional, WithMany, 这三个方法都提供了重载的无参版本,有参方法的参数也都是一个 lambda expression, 前两个用于表示实体关系(Relationship)间的导航属性(navigation property),后一个则是导航属性的集合(Collection

  接下来,你可以使用方法 HasForeignKey 继续配置外键属性,方法的参数仍然是一个 lambda expression, 只不过代表一个属性

DependentNavigationPropertyConfiguration<TDependentEntityType>

  1. public CascadableNavigationPropertyConfiguration HasForeignKey<TKey>(Expression<Func<TDependentEntityType, TKey>> foreignKeyExpression);

  其它两个类主要包含方法 Map ,如下

ForeignKeyNavigationPropertyConfiguration

  1. public CascadableNavigationPropertyConfiguration Map(Action<ForeignKeyAssociationMappingConfiguration> configurationAction);

ManyToManyNavigationPropertyConfiguration<TEntityType, TTargetEntityType>

  1. public ManyToManyNavigationPropertyConfiguration<TEntityType, TTargetEntityType> Map(Action<ManyToManyAssociationMappingConfiguration> configurationAction);
  2. public ManyToManyNavigationPropertyConfiguration<TEntityType, TTargetEntityType> MapToStoredProcedures();
  3. public ManyToManyNavigationPropertyConfiguration<TEntityType, TTargetEntityType> MapToStoredProcedures(Action<ManyToManyModificationStoredProceduresConfiguration<TEntityType, TTargetEntityType>> modificationStoredProcedureMappingConfigurationAction);

  我们可以继续在返回的实例上进行配置

CascadableNavigationPropertyConfiguration

  1. public void WillCascadeOnDelete();
  2. public void WillCascadeOnDelete(bool value);

  我们看到了级联删除

Configuring Relationships

1:1,0 - Configuring a Required-to-Optional Relationship (One-to–Zero-or-One)

  一个学生可以有一个或没有其它信息(包括邮件地址、手机号等)

  1. // Map one-to-zero or one relationship
  2. modelBuilder.Entity<OtherInfo>()
  3. .HasRequired(t => t.Student)
  4. .WithOptional(t => t.OtherInfo);

1:1 - Configuring a Relationship Where Both Ends Are Required (One-to-One)

  一个学生肯定有一个地址信息(包含家庭住址、居住地址)

  1. // Map one-to-one relationship
  2. modelBuilder.Entity<Address>()
  3. .HasRequired(t => t.Student)
  4. .WithRequiredPrincipal(t => t.Address);

1:N - Configuring a Required-to-Many Relationship (One-to-Many)

  一个学生可以参加多门课程

  1. // Map one-to-many relationship
  2. modelBuilder.Entity<Student>()
  3. .HasMany(t => t.Enrollments)
  4. .WithRequired(t => t.Student);

N:N - Configuring a Many-to-Many Relationship (Many-to-Many)

  一个老师可以教授多门课程,一门课程也可以由多名老师教授

  1. // Map one-to-many relationship
  2. modelBuilder.Entity<Course>()
  3. .HasMany(t => t.Instructors)
  4. .WithMany(t => t.Courses);

  你还可以进一步指定中间连接表(数据库将会创建中间连接表)

  1. // Map one-to-many relationship
  2. modelBuilder.Entity<Course>()
  3. .HasMany(t => t.Instructors)
  4. .WithMany(t => t.Courses)
  5. .Map(m =>
  6. {
  7. m.ToTable("CourseInstructor");
  8. m.MapLeftKey("CourseID");
  9. m.MapRightKey("InstructorID");
  10. });

Configuring a Relationship with One Navigation Property - 基于导航属性配置关系

  如果关系是单向的,即两个实体间只在一个实体上定义导航属性。Code First Conventions 能够自动推断这种关系为 one-to-many .

  例如你想在 Student 和 Address 两个实体间建立 one-to-one 关系,而且只在 Address 实体上包含导航属性,此时你就需要用 Code First Fluent API 配置这种关系

  1. // Map one-to-one relationship
  2. modelBuilder.Entity<Address>()
  3. .HasRequired(t => t.Student)
  4. .WithRequiredPrincipal();

WillCascadeOnDelete - Enabling Cascade Delete (级联删除)

  你可以使用 WillCascadeOnDelete 来级联删除关系,如果从属主体上的外键是 not nullable, 那么 Code First 将设置级联删除,否则将不会设置级联删除,而只是仅仅把外键设置成 null

  在 Code First Conventions 下是这样移除级联删除的

  1. modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()
  2. modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>()

  Code First Fluent API 的方式如下

  1. // Cascade Delete
  2. modelBuilder.Entity<Course>()
  3. .HasRequired(t => t.Department)
  4. .WithMany(t => t.Courses)
  5. .HasForeignKey(d => d.DepartmentID)
  6. .WillCascadeOnDelete(false);

Configuring a Composite Foreign Key - 配置组合外键

  如果设置 Department 的主键为组合主键 DepartmentID, Name,则可以通过 Fluent API 为 Course 指定组合外键

  1. // Composite primary key
  2. modelBuilder.Entity<Department>()
  3. .HasKey(d => new { d.DepartmentID, d.Name });
  4.  
  5. // Composite foreign key
  6. modelBuilder.Entity<Course>()
  7. .HasRequired(c => c.Department)
  8. .WithMany(d => d.Courses)
  9. .HasForeignKey(d => new { d.DepartmentID, d.DepartmentName });

Renaming a Foreign Key That Is Not Defined in the Model - 重命名外键

  可以重命名外键名

  1. // Renaming a Foreign Key That Is Not Defined in the Model
  2. modelBuilder.Entity<Course>()
  3. .HasRequired(c => c.Department)
  4. .WithMany(t => t.Courses)
  5. .Map(m => m.MapKey("ChangedDepartmentID"));

Configuring a Foreign Key Name That Does Not Follow the Code First Convention

  如果从属实体上的外键属性名不符合 Code First Conventions 的规范,意即从属实体上没有外键,你可以通过如下方式来指定

  1. // Configuring a Foreign Key Name That Does Not Follow the Code First Convention
  2. modelBuilder.Entity<Course>()
  3. .HasRequired(c => c.Department)
  4. .WithMany(d => d.Courses)
  5. .HasForeignKey(c => c.SomeDepartmentID);

原文链接:http://msdn.microsoft.com/en-us/data/jj591620

Entity Framework Code First (五)Fluent API - 配置关系 转载 https://www.cnblogs.com/panchunting/p/entity-framework-code-first-fluent-api-configuring-relationships.html的更多相关文章

  1. Entity Framework Code First (五)Fluent API - 配置关系

    上一篇文章我们讲解了如何用 Fluent API 来配置/映射属性和类型,本文将把重点放在其是如何配置关系的. 文中所使用代码如下 public class Student { public int ...

  2. Entity Framework Code First属性映射约定 转载https://www.cnblogs.com/libingql/p/3352058.html

    Entity Framework Code First属性映射约定   Entity Framework Code First与数据表之间的映射方式有两种实现:Data Annotation和Flue ...

  3. Entity Framework Code First数据库连接 转载 https://www.cnblogs.com/libingql/p/3351275.html

    Entity Framework Code First数据库连接   1. 安装Entity Framework 使用NuGet安装Entity Framework程序包:工具->库程序包管理器 ...

  4. WebApi系列~基于RESTful标准的Web Api 转载 https://www.cnblogs.com/lori/p/3555737.html

    微软的web api是在vs2012上的mvc4项目绑定发行的,它提出的web api是完全基于RESTful标准的,完全不同于之前的(同是SOAP协议的)wcf和webService,它是简单,代码 ...

  5. Activity详解一 配置、启动和关闭activity转载 https://www.cnblogs.com/androidWuYou/p/5887726.html

    先看效果图: Android为我们提供了四种应组件,分别为Activity.Service.Broadcast receivers和Content providers,这些组建也就是我们开发一个And ...

  6. Entity Framework 实体框架的形成之旅--Code First模式中使用 Fluent API 配置(6)

    在前面的随笔<Entity Framework 实体框架的形成之旅--Code First的框架设计(5)>里介绍了基于Code First模式的实体框架的经验,这种方式自动处理出来的模式 ...

  7. Entity Framework Code First (四)Fluent API - 配置属性/类型

    上篇博文说过当我们定义的类不能遵循约定(Conventions)的时候,Code First 提供了两种方式来配置你的类:DataAnnotations 和 Fluent API, 本文将关注 Flu ...

  8. Code First约定-Fluent API配置

    转自:http://blog.163.com/m13864039250_1/blog/static/2138652482015283397609/ 用Fluent API 配置/映射属性和类型 简介 ...

  9. Entity FrameWork Code First 配置关系

    Has方法与With方法 A.HasRequired(a => a.B).WithOptional(b => b.A);上面一句配置意思就是A类包含B类一个不为null的实例,B类包含A类 ...

随机推荐

  1. Delphi Unicode学习

    String.AnsiString及Tbytes之间的转换一.string转为AnsiString1.直接赋值 (有警告)2.AnsiString()类型强制转换.(无警告) 二.AnsiString ...

  2. C# 中常见的控件以及功能

    1.StatusBar控件——显示各种状态信息. StatusBar控件可以有状态栏面板(用于显示图标以指示状态)或一系列动画图标(用于指示某个进程正在工作,例如,表示正在保存文档的 Microsof ...

  3. C#取模的理解:为什么当a<b,a%b=a?

    一,取模a%b 1,如果a>b,例如10%7=3,这是什么原因呢?可以根据下面的理解 10 =7*1+3,则模就是3 2,如果a<b,例如7%10 = 7,这时怎么得到的呢?根据下面来理解 ...

  4. Vue实现点击li变色

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  5. CentOS7 systemctl 命令

    *启动.重启.停止.重载服务 # systemctl start httpd.service # systemctl restart httpd.service # systemctl stop ht ...

  6. 05XML

    1.XML入门 1.1 引入 HTML, 超文本标记语言. html语言语法是很松散的! 1)标签不区分大小写的! 2)标签可以不匹配的. 由w3c组织,针对html的语法缺陷,去设计了另一门,叫xm ...

  7. 记录一次 Linux crontab 执行django 脚本 失败 的经历和解决办法

    目的是想通过定时任务来执行一次数据统计,本来可以用celery来做,但是想着这个项目整个就没用到异步的地方,所以决定用crontab来做.之前做过数据库的热备份,想来用该没啥问题,但是现实打脸啪啪响. ...

  8. 【转载】Mysql注入点在limit关键字后面的利用方法

      描写sql注入利用方法的文章数不胜数,本文将描述一种比较特殊的场景. 细节 在一次测试中,我碰到了一个sql注入的问题,在网上没有搜到解决办法,当时的注入点是在limit关键字后面,数据库是MyS ...

  9. DispatcherServlet的工作原理

    下面是DispatcherServlet的工作原理图,图片来源于网络. 下面是我从DispatcherServlet源码层面来分析其工作流程: 1.请求到达后,调用HandlerMapping来查找对 ...

  10. 机器学习:2.NPL自然语言处理

    1. 词带的简单解释: 每一个词出现了多少次,缺点是不知道顺序 2.seq2seq自然语言处理的核心 RNN: 一对一:输入一个,输出一个 一对多:输入一个,输出多个 多对一:输入多个,输出一个 多对 ...