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

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

  文中所使用代码如下

public class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public DateTime EnrollmentDate { get; set; }

        // Navigation properties
        public virtual Address Address { get; set; }
        public virtual OtherInfo OtherInfo { get; set; }
        public virtual ICollection<Enrollment> Enrollments { get; set; }
    }

    public class Department
    {
        public Department()
        {
            this.Courses = new HashSet<Course>();
        }
        // Primary key
        public int DepartmentID { get; set; }
        public string Name { get; set; }
        public decimal Budget { get; set; }
        public System.DateTime StartDate { get; set; }
        public int? Administrator { get; set; }

        // Navigation property
        public virtual ICollection<Course> Courses { get; private set; }
    }

    public class Course
    {
        public int CourseID { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }

        // Foreign key
        public int DepartmentID { get; set; }
        public string DepartmentName { get; set; }

        public int SomeDepartmentID { get; set; }

        // Navigation properties
        public virtual Department Department { get; set; }
        public virtual ICollection<Enrollment> Enrollments { get; set; }
        public virtual ICollection<Instructor> Instructors { get; set; }
    }

    public class Instructor
    {
        public int InstructorID { get; set; }
        public string Name { get; set; }
        public DateTime HireDate { get; set; }

        // Navigation properties
        public virtual ICollection<Course> Courses { get; set; }
    }

    public class Enrollment
    {
        public int EnrollmentID { get; set; }
        public int CourseID { get; set; }
        public int StudentID { get; set; }

        // Navigation property
        public virtual Course Course { get; set; }
        public virtual Student Student { get; set; }
    }

    public class Address
    {
        public int AddressId { get; set; }
        public string HomeAddress { get; set; }
        public string LiveAddress { get; set; }

        // Navigation property
        public virtual Student Student { get; set; }
    }

    public class OtherInfo
    {
        public int Id { get; set; }
        public string HomeAddress { get; set; }
        public string MailAddress { get; set; }
        public string PhoneNumber { get; set; }
        public string StudentID { get; set; }

        // Navigation property
        public virtual Student Student { get; set; }
    }

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>

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

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

ForeignKeyNavigationPropertyConfiguration

public CascadableNavigationPropertyConfiguration Map(Action<ForeignKeyAssociationMappingConfiguration> configurationAction);

ManyToManyNavigationPropertyConfiguration<TEntityType, TTargetEntityType>

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

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

CascadableNavigationPropertyConfiguration

public void WillCascadeOnDelete();
public void WillCascadeOnDelete(bool value);

  我们看到了级联删除

Configuring Relationships

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

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

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

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

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

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

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

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

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

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

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

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

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

// Map one-to-many relationship
modelBuilder.Entity<Course>()
    .HasMany(t => t.Instructors)
    .WithMany(t => t.Courses)
    .Map(m =>
    {
        m.ToTable("CourseInstructor");
        m.MapLeftKey("CourseID");
        m.MapRightKey("InstructorID");
    });

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

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

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

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

WillCascadeOnDelete - Enabling Cascade Delete (级联删除)

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

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

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

  Code First Fluent API 的方式如下

// Cascade Delete
modelBuilder.Entity<Course>()
    .HasRequired(t => t.Department)
    .WithMany(t => t.Courses)
    .HasForeignKey(d => d.DepartmentID)
    .WillCascadeOnDelete(false);

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

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

// Composite primary key
modelBuilder.Entity<Department>()
    .HasKey(d => new { d.DepartmentID, d.Name });

// Composite foreign key
modelBuilder.Entity<Course>()
    .HasRequired(c => c.Department)
    .WithMany(d => d.Courses)
    .HasForeignKey(d => new { d.DepartmentID, d.DepartmentName });

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

  可以重命名外键名

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

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

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

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

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

参考页面:

http://www.yuanjiaocheng.net/entity/change-tracking.html

http://www.yuanjiaocheng.net/ASPNET-CORE/asp-net-core-overview.html

http://www.yuanjiaocheng.net/mvc/partial-view-in-asp.net-mvc.html

http://www.yuanjiaocheng.net/CSharp/Csharp-operators.html

http://www.yuanjiaocheng.net/Java/java-features.html

http://www.yuanjiaocheng.net/mvc/viewdata-in-asp.net-mvc.html

http://www.yuanjiaocheng.net/entity/update-entity-graph.html

http://www.yuanjiaocheng.net/webapi/web-api-gaisu.html

http://www.yuanjiaocheng.net/mvc/mvc-helper-Label.html

http://www.yuanjiaocheng.net/Linq/linq-tutorials.html

http://www.yuanjiaocheng.net/CSharp/Csharp-Generics.html

时间: 2024-12-26 03:08:04

Entity Framework Code First (五)Fluent API - 配置关系的相关文章

Code First约定-Fluent API配置

转自:http://blog.163.com/m13864039250_1/blog/static/2138652482015283397609/ 用Fluent API 配置/映射属性和类型 简介 通常通过重写派生DbContext 上的OnModelCreating 方法来访问Code First Fluent API.以下示例旨在显示如何使用 Fluent API 执行各种任务,您可以将代码复制出来并进行自定义,使之适用于您的模型. 属性映射 Property 方法用于为每个属于实体或复杂

Entity Framework Code First关系映射约定

Entity Framework Code First关系映射约定 本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个不同表之间可以存在外键依赖关系,一个表自身也可以有自反关系(表中的一个字段引用主键,从而也是外键字段). Entity Framework Code First默认多重关系的一些约定规则: 一对多关系:两个类中分别包含一个引用和一个

Entity Framework Code First主外键关系映射约定

本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个不同表之间可以存在外键依赖关系,一个表自身也可以有自反关系(表中的一个字段引用主键,从而也是外键字段). Entity Framework Code First默认多重关系的一些约定规则: 一对多关系:两个类中分别包含一个引用和一个集合属性,也可以是一个类包含另一个类的引用属性,或一个类包含另一个类

Entity Framework Code First关系映射约定【l转发】

本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个不同表之间可以存在外键依赖关系,一个表自身也可以有自反关系(表中的一个字段引用主键,从而也是外键字段). Entity Framework Code First默认多重关系的一些约定规则: 一对多关系:两个类中分别包含一个引用和一个集合属性,也可以是一个类包含另一个类的引用属性,或一个类包含另一个类

使用Fluent API 配置/映射属性和类型

Code First约定-Fluent API配置 使用Fluent API 配置/映射属性和类型 简介 通常通过重写派生DbContext 上的OnModelCreating 方法来访问Code First Fluent API.以下示例旨在显示如何使用 Fluent API 执行各种任务,您可以将代码复制出来并进行自定义,使之适用于您的模型. 属性映射 使用Fluent API 配置/映射属性和类型 简介 通常通过重写派生DbContext 上的OnModelCreating 方法来访问Co

Entity Framework Code First (一)Conventions

Entity Framework 简言之就是一个ORM(Object-Relational Mapper)框架. Code First 使得你能够通过C#的类来描述一个模型,模型如何被发现/检测就是通过一些约定(Conventions).Conventions 就是一系列规则的集合,被用于对基于类别定义的概念模型的自动装配. 这些约定都被定义于 System.Data.Entity.ModelConfiguration.Conventions 命名空间下. 当然你可以进一步地对你的模型作出配置,

Entity Framework Code First (三)Data Annotations

Entity Framework Code First 利用一种被称为约定(Conventions)优于配置(Configuration)的编程模式允许你使用自己的 domain classes 来表示 EF 所依赖的模型去执行查询.更改追踪.以及更新功能,这意味着你的 domain classes 必须遵循 EF 所使用的约定.然而,如果你的 domain classes 不能遵循 EF 所使用的约定,此时你就需要有能力去增加一些配置使得你的 classes 能够满足 EF 所需要的信息. C

Entity Framework Code First属性映射约定

参考页面: http://www.yuanjiaocheng.net/entity/code-first.html http://www.yuanjiaocheng.net/entity/mode-first.html http://www.yuanjiaocheng.net/entity/database-first.html http://www.yuanjiaocheng.net/entity/choose-development-approach.html http://www.yuan

Entity Framework Code First (二)Custom Conventions

------------------------------------------------------------------------------------------------------------ 注意:以下所讨论的功能或 API 等只针对 Entity Framework 6 ,如果你使用早期版本,可能部分或全部功能不起作用! --------------------------------------------------------------------------