Entity Framework Code First (five) Fluent API - Configuration relations reprint https://www.cnblogs.com/panchunting/p/entity-framework-code-first-fluent-api-configuring-relationships.html

  Previous article we explain how to use  Fluent API  to configure / map attributes and types, this article will focus on how it is configured relationships.

  As used herein the following code

Copy the code
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; }
    }
Copy the code

 

EntityTypeConfiguration<TEntityType>

  The above method is part of a generic class of shots, we generally by  Code First Fluent API  instance is to configure the relationship between entities is beginning from a generic class, this class provides a generic approach for the majority of our relationship, such as must  HasRequired  , optional  HasOptional, more  hasMany.

  All of the above methods (except  hasMany, HasOptional, HasRequired  ) is the return value of the generic class  EntityTypeConfiguration <TEntityType>  Examples of itself, to which the chain provides great convenience to operation.

  HasRequired,  HasOptional,  hasMany  these three parameters is a method of  the lambda expression The , except for the first two entities representing the relationship ( Relationship navigation properties (inter) Navigation Property ), the latter is a collection of navigation attributes ( Collection )

  HasRequired,  HasOptional,  hasMany  return values of these three methods is to continue to be a generic class instance configuration, although the names are different, the method name is slightly different, but the main method embodied idea is the same

RequiredNavigationPropertyConfiguration<TEntityType, TTargetEntityType>

OptionalNavigationPropertyConfiguration<TEntityType, TTargetEntityType>

ManyNavigationPropertyConfiguration<TEntityType, TTargetEntityType>

  Three generic classes have the following three methods analogous  WithRequired, WithOptional, WithMany , these three methods are no arguments provided overloaded version, there is also reference a process parameter  the lambda expression The , for the first two represent an entity relationship ( relationship navigation properties (inter) navigation property ), the latter is a collection of navigation attributes ( collection )

  Next, you can use  HasForeignKey  continue to configure the foreign key attribute, a parameter method is still  the lambda expression The , but on behalf of a property

DependentNavigationPropertyConfiguration<TDependentEntityType>

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

  Other methods comprise two major classes  the Map  , the following

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);

  We can continue to be configured on the instances returned

CascadableNavigationPropertyConfiguration

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

  We see the cascading deletes

 

Configuring Relationships

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

  A student can have one or no other information (including mailing address, phone number, etc.)

// 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)

  A student must have an address information (including home address, residential address)

// 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)

  A student can take many courses

// 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)

  A teacher can teach many courses, a course can also be taught by several teachers

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

  You can further specify intermediate join table (database would create an intermediate connection table)

Copy the code
// 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");
    });
Copy the code

Configuring a Relationship with One Navigation Property - Configuration relations based navigation properties

  If the relationship is unidirectional, i.e. only two entities in one entity definition navigation attributes. Code First Conventions  can automatically infer this relationship is  one-to-many.

  For example, you want to  Student  and  Address  established between the two entities  one-to-one  relationship, and only in the  Address  contains navigation properties on entity, then you will need to use  Code First Fluent API  configuration relationship

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

WillCascadeOnDelete - Enabling Cascade Delete (cascade delete)

  You can use  WillCascadeOnDelete  to cascade delete relationship, if the foreign key on the slave body is not Nullable , then the  Code First  will set up cascading deletes, or they will not set up cascading deletes, but rather only the foreign key set to  null 

   In the  Code First Conventions  under is removed cascading deletes

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

  Code First Fluent API  is as follows

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

Configuring a Composite Foreign Key - foreign key configuration combinations

  If  Department  primary key for the primary key combination  DepartmentID, Name, it can  Fluent API  is  Course  given combination foreign key

Copy the code
// 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 });
Copy the code

Renaming a Foreign Key That Is Not Defined in the Model - foreign key rename

  You can rename the foreign key name

// 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

  If the foreign key attribute names on the slave entity does not meet  Code First Conventions  specification, meaning that there is no slave entity foreign keys, you can specify the following manner

// 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);

Original link: http://msdn.microsoft.com/en-us/data/jj591620

Guess you like

Origin www.cnblogs.com/Jeely/p/10954433.html