Use Fluent API to configure/map attributes and types, fluentapi

Source: Internet
Author: User

Use Fluent API to configure/map attributes and types, fluentapi
Use Fluent API to configure/map attributes and types

When Code First is used, the default behavior is to map POCO classes to tables using a set of embedded conventions in EF. However, sometimes you cannot or do not want to comply with these conventions, You need to map entities to other objects beyond the conventions.

You can configure EF to bypass the Conventions when ing data in two ways: annotation and EF Fluent API. Annotations only cover a part of Fluent API functions. Therefore, annotations cannot be used in some cases. This document demonstrates how to use Fluent APIs to configure attributes.

In addition to controlling ing, Fluent APIs and annotations can also be used to configure constraints, such as field length or required attributes, the constraints of these configurations will affect the verification of the database created by Code First and the Entity Framework.

 

Content
  • Introduction
  • Property ing
    • Configure primary keys
    • Configure the primary key combination
    • Disables the ID of a numeric primary key.
    • Specifies the maximum length of an attribute.
    • Set Properties as required
    • Specify not to map CLR attributes to columns in the database
    • Map CLR attributes to specific columns in the database
    • Rename an undefined foreign key in the Model
    • Configure whether the string attribute supports Unicode content
    • Configure the Data Type of the database Column
    • Configure attributes of complex types
    • Configure the attribute as an optimistic concurrency token
  • Type ing
    • Specify a class as a complex type
    • Specifies that the CLR entity type is not mapped to a table in the database.
    • Map the CLR object type to a specific table in the database
    • Ing "one table per hierarchy (TPH)" to inherit
    • Ing "one table for each type (TPT)" to inherit
    • Ing "one table for each specific class (TPC)" to inherit
    • Map object-type CLR attributes to multiple tables in the database (entity splitting)
    • Map Multiple object types to a table in the database (Table sharding)
  • Model Used in the example

 

 

Introduction

Generally, you can access the Code First Fluent API by rewriting the OnModelCreating method on the derived DbContext. The following example shows how to use the Fluent API to execute various tasks. You can copy the code and customize it to apply it to your model. If you want to view the models that can use these examples as they are, this model is provided at the end of this article.

 

Property ing

The Property method is used to configure properties for each attribute of an entity or complex type. The Property method is used to obtain the configuration object of a given Property. The options on the configuration object are specific to the type to be configured. For example, IsUnicode can only be used for string attributes.

Configure primary keys

The Entity Framework Conventions on primary keys are as follows:

1. Attributes of your class definition name "ID" or "Id"

2. Or the class name is followed by "ID" or "Id ".

To explicitly set an attribute as a primary key, use the HasKey method. In the following example, the HasKey method is used to configure the InstructorID primary key for the OfficeAssignment type.

modelBuilder.Entity<OfficeAssignment>().HasKey(t => t.InstructorID);
Configure the primary key combination

The following example shows how to configure the dimension mentid and Name attributes of the Department-type combination primary key.

modelBuilder.Entity<Department>().HasKey(t => new { t.DepartmentID, t.Name });
Disables the ID of a numeric primary key.

In the following example, the DepartmentID attribute is set to System. ComponentModel. DataAnnotations. DatabaseGeneratedOption. None to indicate that this value is not generated by the database.

modelBuilder.Entity<Department>().Property(t => t.DepartmentID)     .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
Specifies the maximum length of an attribute.

In the following example, the Name attribute cannot exceed 50 characters. If the value exceeds 50 characters, a DbEntityValidationException exception occurs. If Code First creates a database based on this model, it also sets the maximum length of the Name column to 50 characters.

modelBuilder.Entity<Department>().Property(t => t.Name).HasMaxLength(50);
Set Properties as required

In the following example, the Name attribute is required. If no Name is specified, DbEntityValidationException occurs. If Code First creates a database based on this model, the columns used to store this attribute cannot be empty.

modelBuilder.Entity<Department>().Property(t => t.Name).IsRequired();
Specify not to map CLR attributes to columns in the database

The following example shows how to specify that attributes of the CLR type are not mapped to columns in the database.

modelBuilder.Entity<Department>().Ignore(t => t.Budget);
Map CLR attributes to specific columns in the database

The following example maps the Name CLR attribute to the DepartmentName database column.

modelBuilder.Entity<Department>()     .Property(t => t.Name)     .HasColumnName("DepartmentName");
Rename an undefined foreign key in the Model

If you choose not to define a foreign key for the CLR type, but want to specify the name it should use in the database, please encode as follows:

modelBuilder.Entity<Course>()     .HasRequired(c => c.Department)     .WithMany(t => t.Courses)     .Map(m => m.MapKey("ChangedDepartmentID"));
Configure whether the string attribute supports Unicode content

By default, the string is Unicode (nvarchar in SQL Server ). You can use the IsUnicode method to specify that the string should be of the varchar type.

modelBuilder.Entity<Department>()     .Property(t => t.Name)     .IsUnicode(false);
Configure the Data Type of the database Column

The HasColumnType method supports ing to different representations of the same basic type. Using this method does not support any data conversion at runtime. Note that IsUnicode is the preferred method for setting columns to varchar because it is irrelevant to the database.

modelBuilder.Entity<Department>()     .Property(p => p.Name)     .HasColumnType("varchar");
Configure attributes of complex types

You can configure scalar attributes for complex types.

You can call Property for ComplexTypeConfiguration.

modelBuilder.ComplexType<Details>()     .Property(t => t.Location)     .HasMaxLength(20);

You can also use dot notation to access attributes of complex types.

modelBuilder.Entity<OnsiteCourse>()     .Property(t => t.Details.Location)     .HasMaxLength(20);
Configure the attribute as an optimistic concurrency token

To specify an attribute in an object to represent a concurrent Token, you can use the ConcurrencyCheck feature or the IsConcurrencyToken method.

modelBuilder.Entity<OfficeAssignment>()     .Property(t => t.Timestamp)     .IsConcurrencyToken();

You can also use the IsRowVersion method to set the attribute to the row version in the database. Setting the attribute to the row version will automatically configure it as an optimistic concurrency token.

modelBuilder.Entity<OfficeAssignment>()     .Property(t => t.Timestamp)     .IsRowVersion();
Type ing specifies a class as a complex type

As agreed, a type without a primary key is considered as a complex type. In some cases, Code First does not detect complex types (for example, if you have an attribute named "ID" but do not want to use it as a primary key ). In this case, you will use the Fluent API to explicitly specify a type as a complex type.

modelBuilder.ComplexType<Details>();
Specifies that the CLR entity type is not mapped to a table in the database.

The following example shows how to exclude a CLR type so that it is not mapped to a table in the database.

modelBuilder.Ignore<OnlineCourse>();
Map the CLR object type to a specific table in the database

All properties of Department are mapped to columns in the table named t _ Department.

modelBuilder.Entity<Department>()  
    .ToTable("t_Department");

You can also specify the architecture name as follows:

modelBuilder.Entity<Department>()  
    .ToTable("t_ Department", "school");
Ing "one table per hierarchy (TPH)" to inherit

In the case of TPH ing, all types in the inheritance hierarchy are mapped to the same table. The Authenticator column is used to identify the type of each row. When Code First is used to create a model, TPH participates in the Default policy used to inherit the type of the hierarchy. By default, the authenticator column is added to the table named "Discriminator", and each type of CLR type name in the hierarchy is used as the authenticator value. You can use the Fluent API to modify the default behavior.

modelBuilder.Entity<Course>()  
    .Map<Course>(m => m.Requires("Type").HasValue("Course"))  
    .Map<OnsiteCourse>(m => m.Requires("Type").HasValue("OnsiteCourse"));
Ing "one table for each type (TPT)" to inherit

In the case of TPT ing, all types are mapped to different tables. Only attributes of a base type or derived type are stored in a table mapped to this type. A table mapped to a derived type also stores a foreign key that connects the derived table to the base table.

modelBuilder.Entity<Course>().ToTable("Course");  
modelBuilder.Entity<OnsiteCourse>().ToTable("OnsiteCourse");
Ing "one table for each specific class (TPC)" to inherit

In the case of TPC ing, all non-abstract types in the hierarchy are mapped to different tables. A table mapped to a derived class has no relationship with a table mapped to a base class in the database. All attributes of the class (including the inherited attributes) are mapped to the columns of the corresponding table.

Call the MapInheritedProperties method to configure each derived type. MapInheritedProperties re-maps all attributes inherited from the base class to the new columns in the derived class table.

Note:Because tables that belong to the TPC hierarchy do not use the same primary key, if you want the values generated by the database to have the same identification seed, when you perform the insert operation in the table mapped to the subclass, duplicate entity keys are generated. To solve this problem, you can specify different initial seed values for each table or disable the primary key attribute identifier. When Code First is used, the identifier is the default value of the integer key attribute.

modelBuilder.Entity<Course>()     .Property(c => c.CourseID)     .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);  modelBuilder.Entity<OnsiteCourse>().Map(m => {     m.MapInheritedProperties();     m.ToTable("OnsiteCourse"); });  modelBuilder.Entity<OnlineCourse>().Map(m => {     m.MapInheritedProperties();     m.ToTable("OnlineCourse"); });
Map object-type CLR attributes to multiple tables in the database (entity splitting)

Object splitting allows attributes of an object type to be dispersed in multiple tables. In the following example, the Department entity is split into two tables: Department and DepartmentDetails. Object splitting maps some attributes to a specific table by calling the Map method multiple times.

modelBuilder.Entity<Department>()    .Map(m =>    {        m.Properties(t => new { t.DepartmentID, t.Name });        m.ToTable("Department");    })    .Map(m =>    {        m.Properties(t => new { t.DepartmentID, t.Administrator, t.StartDate, t.Budget });        m.ToTable("DepartmentDetails");    });
Map Multiple object types to a table in the database (Table sharding)

The following example maps two entity types of the same primary key to the same table.

modelBuilder.Entity<OfficeAssignment>()     .HasKey(t => t.InstructorID);              modelBuilder.Entity<Instructor>()     .HasRequired(t => t.OfficeAssignment)     .WithRequiredPrincipal(t => t.Instructor);  modelBuilder.Entity<Instructor>().ToTable("Instructor");  modelBuilder.Entity<OfficeAssignment>().ToTable("Instructor");
Model Used in the example

The following Code First model is used as an example on this page.

using System.Data.Entity; using System.Data.Entity.ModelConfiguration.Conventions; // add a reference to System.ComponentModel.DataAnnotations DLL using System.ComponentModel.DataAnnotations; using System.Collections.Generic; using System;  public class SchoolEntities : DbContext {     public DbSet<Course> Courses { get; set; }     public DbSet<Department> Departments { get; set; }     public DbSet<Instructor> Instructors { get; set; }     public DbSet<OfficeAssignment> OfficeAssignments { get; set; }      protected override void OnModelCreating(DbModelBuilder modelBuilder)     {         // Configure Code First to ignore PluralizingTableName convention         // If you keep this convention then the generated tables will have pluralized names.         modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();     } }  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 Course()     {         this.Instructors = new HashSet<Instructor>();     }     // Primary key     public int CourseID { get; set; }      public string Title { get; set; }     public int Credits { get; set; }      // Foreign key     public int DepartmentID { get; set; }      // Navigation properties     public virtual Department Department { get; set; }     public virtual ICollection<Instructor> Instructors { get; private set; } }  public partial class OnlineCourse : Course {     public string URL { get; set; } }  public partial class OnsiteCourse : Course {     public OnsiteCourse()     {         Details = new Details();     }      public Details Details { get; set; } }  public class Details {     public System.DateTime Time { get; set; }     public string Location { get; set; }     public string Days { get; set; } }      public class Instructor {     public Instructor()     {         this.Courses = new List<Course>();     }      // Primary key     public int InstructorID { get; set; }     public string LastName { get; set; }     public string FirstName { get; set; }     public System.DateTime HireDate { get; set; }      // Navigation properties     public virtual ICollection<Course> Courses { get; private set; } }  public class OfficeAssignment {     // Specifying InstructorID as a primary     [Key()]     public Int32 InstructorID { get; set; }      public string Location { get; set; }      // When the Entity Framework sees Timestamp attribute     // it configures ConcurrencyCheck and DatabaseGeneratedPattern=Computed.     1434704210     public Byte[] Timestamp { get; set; }      // Navigation property     public virtual Instructor Instructor { get; set; } }

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.