• Entity Framework Code First (四)Fluent API


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

      一般来说我们访问 Fluent API 是通过重写继承自 DbContext 的类中方法 OnModelCreating. 为了便于例示,我们先创建一个继承自 DbContext 的类,以及其它的一些类以便使用

    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.
            [Timestamp]
            public Byte[] Timestamp { get; set; }
    
            // Navigation property
            public virtual Instructor Instructor { get; set; }
        }
    View Code

    Model-Wide Setting

     HasDefaultSchema() - Default Schema(EF6 onwards)

      从 EF6 开始可以使用 DbModelBuilder 中的方法 HasDefaultSchema 来指定所有的表/存储过程/视图等属于哪一个 database schema 

    modelBuilder.HasDefaultSchema("sales");

      PS 1: EF 之前的版本中默认的 schema 是被 hard-coded 成 "dbo", 唯一改变它的方式是使用 ToTable API

      PS 2: 解释一下 database schema, 它就是对诸如表、视图、存储过程等的一种逻辑分组的方式(可以想象成对象的集合),你可以把一个 schema 赋予用户以便他能够访问所有经过授权的对象。Schemas 在数据库中可以被创建并被更新,用户也可以被授权访问它,一个 schema 可以被定义成任意用户拥有,并且 schema 的所有权是可以被转移的。我们可以看一下数据库中的 schema 

    Custom Conventions(EF6 onwards)

      约定配置请参考文章 http://www.cnblogs.com/panchunting/p/entity-framework-code-first-custom-conventions.html

    Property Mapping 属性映射

    HasKey() - Primary Key

      指定属性为主键 

    // Primary Key
    modelBuilder.Entity<OfficeAssignment>()
                .HasKey(t => t.InstructorID);

      也可以指定多个属性为联合主键

    // Composite Primary Key
    modelBuilder.Entity<Department>()
                .HasKey(t => new { t.DepartmentID, t.Name });

    HasDatabaseGeneratedOption()

      为数字型主键取消数据库生成

    // Switching off Identity for Numeric Primary Keys
    modelBuilder.Entity<Department>()
                .Property(t => t.DepartmentID)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

    HasMaxLength() - Specifying the Length on a Property

      指定属性长度

    // Specifying the Maximum Length on a Property
    modelBuilder.Entity<Department>()
                .Property(t => t.Name)
                .HasMaxLength(50);

    IsRequired() - Configuring the Property to be Required

      必填字段

    // Configuring the Property to be Required
    modelBuilder.Entity<Department>()
                .Property(t => t.Name)
                .IsRequired();

    Ignore() - Specifying Not to Map a CLR Property to a Column in the Database

      忽略

    // Specifying Not to Map a CLR Property to a Column in the Database
    modelBuilder.Entity<Department>()
                .Ignore(t => t.Budget);

    HasColumnName() - Mapping a CLR Property to a Specific Column in the Database

      指定列名

    // Mapping a CLR Property to a Specific Column in the Database
    modelBuilder.Entity<Department>()
                .Property(t => t.Name)
                .HasColumnName("DepartmentName");

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

    HasColumnType() - Configuring the Data Type of a Database Column

      指定列类型

    // Configuring the Data Type of a Database Column
    modelBuilder.Entity<Department>()
                .Property(p => p.Name)
                .HasColumnType("varchar");

    Configuring Properties on a Complex Type

      在复杂类型(Complex Type)上有两种方式来配置 scalar properties

      在 ComplexTypeConfiguration 上调用 Property

    // Call Property on ComplexTypeConfiguration
    modelBuilder.ComplexType<Details>()
                .Property(t => t.Location)
                .HasMaxLength(20);

      也可以使用点标记法来访问复杂类型上的属性

     // Use the dot notation to access a property of a complex type
     modelBuilder.Entity<OnsiteCourse>()
                 .Property(t => t.Details.Location)
                 .HasMaxLength(20);

    IsConcurrencyToken() - Configuring a Property to Be Used as an Optimistic Concurrency Token

      设置乐观并发标记

    // Configuring a Property to Be Used as an Optimistic Concurrency Token
    modelBuilder.Entity<OfficeAssignment>()
                .Property(t => t.Timestamp)
                .IsConcurrencyToken();

    IsRowVersion() - Configuring a Property to Be Used as an Optimistic Concurrency Token

      设置乐观并发标记,效果同上

    // Configuring a Property to Be Used as an Optimistic Concurrency Token
    modelBuilder.Entity<OfficeAssignment>()
                .Property(t => t.Timestamp)
                .IsRowVersion();

    Type Mapping类型映射

    ComplexType() - Specifying That a Class Is a Complex Type

      指定复杂类型

    // Specifying That a Class Is a Complex Type
    modelBuilder.ComplexType<Details>();

    Ingore() - Specifying Not to Map a CLR Entity Type to a Table in the Database

      忽略实体类型

    // Specifying Not to Map a CLR Entity Type to a Table in the Database
    modelBuilder.Ignore<OnlineCourse>();

    ToTable() - Mapping an Entity Type to a Specific Table in the Database

      映射表名

    // Mapping an Entity Type to a Specific Table in the Database
    modelBuilder.Entity<Department>()
                .ToTable("t_Department");

      也可以同时指定 schema

    // Mapping an Entity Type to a Specific Table in the Database
    modelBuilder.Entity<Department>()
                .ToTable("t_ Department", "school");

    Mapping the Table-Per-Hierarchy (TPH) Inheritance

      映射 TPH

    // Mapping the Table-Per-Hierarchy (TPH) Inheritance
    modelBuilder.Entity<Course>()
                .Map<Course>(m => m.Requires("Type").HasValue("Course"))
                .Map<OnsiteCourse>(m => m.Requires("Type").HasValue("OnsiteCourse"));

    Mapping the Table-Per-Type (TPT) Inheritance

      映射 TPT

    // Mapping the Table-Per-Type (TPT) Inheritance
    modelBuilder.Entity<Course>().ToTable("Course");
    modelBuilder.Entity<OnsiteCourse>().ToTable("OnsiteCourse");

    Mapping the Table-Per-Concrete Class (TPC) Inheritance

      映射 TPC

    // Mapping the Table-Per-Concrete Class (TPC) Inheritance
    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");
                });

    Mapping Properties of an Entity Type to Multiple Tables in the Database (Entity Splitting)

      映射实体中属性到多张表中

    • 实体 Department 属性 DepartmentID, Name 映射到表 Department;
    • 同时属性  DepartmentID, Administrator, StartDate, Budget  映射到表 DepartmentDetails 
    // Mapping Properties of an Entity Type to Multiple Tables in the Database (Entity Splitting)
    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");
                });

    Mapping Multiple Entity Types to One Table in the Database (Table Splitting)

      映射多个实体到一张表:实体 Instructor 和 OfficeAssignment 映射到同一张表 Instructor

    // Mapping Multiple Entity Types to One Table in the Database (Table Splitting)
    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");

    Mapping an Entity Type to Insert/Update/Delete Stored Procedures (EF6 onwards)

      映射实体到增、改、更、删 存储过程,详情请参考文章 http://www.cnblogs.com/panchunting/p/entity-framework-code-first-insert-update-delete-stored-procedures

    PS: 关于TPH, TPT, TPC 以后有时间专门写一篇文章介绍 

    原文参考:http://msdn.microsoft.com/en-us/data/jj591617

     摘抄:http://www.cnblogs.com/panchunting/p/entity-framework-code-first-fluent-api-configuring-mapping-properties-and-types.html

     
     
     
  • 相关阅读:
    BZOJ.3990.[SDOI2015]排序(DFS)
    BZOJ.1040.[ZJOI2008]骑士(树形DP)
    BZOJ.2246.[SDOI2011]迷宫探险(DP 记忆化搜索 概率)
    BZOJ.3209.花神的数论题(数位DP)
    UVA.1640.The Counting Problem / BZOJ.1833.[ZJOI2010]数字计数(数位DP)
    HDU.3652.B-number(数位DP)
    BZOJ.4514.[SDOI2016]数字配对(费用流SPFA 二分图)
    BZOJ.4832.[Lydsy1704月赛]抵制克苏恩(期望DP)
    BZOJ.1025.[SCOI2009]游戏(背包DP)
    BZOJ.3257.树的难题(树形DP)
  • 原文地址:https://www.cnblogs.com/caoyc/p/5820862.html
Copyright © 2020-2023  润新知