zoukankan      html  css  js  c++  java
  • asp.net core系列 27 EF模型配置(索引,备用键,继承)

    一.索引

      索引是许多数据存储中的常见概念。虽然它们在数据存储中的实现可能会有所不同,但它们可用于更有效地基于列(或列集)进行查找。按照约定,用作外键每个属性 (或组的属性) 会自动创建索引。无法使用数据注释创建索引。

      

      1.1 非唯一索引

        Fluent API 在单个属性上指定索引。默认情况下,索引是非唯一的。如下代码示例在Blogs表上创建Url列索引:

    class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Blog>()
                .HasIndex(b => b.Url);
        }
    }

        

      1.2 唯一索引

        下面代码指定索引是唯一的,这是在索引上加了(Unique)唯一约束。

            modelBuilder.Entity<Blog>()
                .HasIndex(b => b.Url)
                .IsUnique();

      1.3 复合索引

     class MyContext : DbContext
    {
        public DbSet<People> People { get; set; }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Person>()
                .HasIndex(p => new { p.FirstName, p.LastName });
        }
    }
    
    public class People
    {
        public int PersonId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Address{get;set;}
    }

        下面使用EF基于数据模型(People)创建数据表。在Migration中生成了索引的代码, 以及查看数据库People表的索引(官方文档中暂没有看到提供索引包含列设置)如下所示:

             name: "IX_People_FirstName_LastName",
             table: "People",
             columns: new[] { "FirstName", "LastName" });

          

    二.备用键

             除主键之外,备用键用作每个实体实例的备用唯一标识符(跟主键一样具有唯一约束)。备用键可以用作关系的目标。当使用关系数据库时,这映射到备用键列上的唯一索引/约束的概念以及引用列的一个或多个外键约束。系统通常会在需要时为你引入备用键,你无需手动配置它们。不能使用数据注释配置备用键。

      

      2.1 约定

        按照约定,系统将在识别属性(不是主键)时为你引入备用键,充当关系的目标。如下面代码所示:

    class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Post>()
                .HasOne(p => p.Blog)
                .WithMany(b => b.Posts)
                 //Post中创建BlogUrl外建字段
                .HasForeignKey(p => p.BlogUrl)
                //Blog中设置唯一约束备份键
                .HasPrincipalKey(b => b.Url);
        }
    }
    
    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
    
        public List<Post> Posts { get; set; }
    }
    
    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
    
        public string BlogUrl { get; set; }
        public Blog Blog { get; set; }
    }

      上面主体实体Blog中Url属性作为备用键,创建了AK_Blogs_Url唯一非聚集索引。在依赖实体Post中创建了BlogUrl外键字段, 使用EF基于数据模型(Blog和Post实体)创建数据库,如下图所示。

      

      2.2 Fluent API

        可以使用Fluent API将单个属性配置为备用键。

        class MyContext : DbContext
    {
        public DbSet<Car> Cars { get; set; }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Car>()
                //配置备用键(唯一非聚集索引)
                .HasAlternateKey(c => c.LicensePlate);
    
                //  创建复合备用键
                //  modelBuilder.Entity<Car>()
                // .HasAlternateKey(c => new { c.State, c.LicensePlate });
        }
    }
    
    class Car
    {
        public int CarId { get; set; }
        public string LicensePlate { get; set; }
        public string Make { get; set; }
        public string Model { get; set; }
        public string State { get; set; }
    }

    三.继承

       EF 模型中的继承用于控制如何在数据库中表示实体类中的继承, 按照约定,由数据库提供程序决定如何在数据库中表示继承。有关如何使用关系数据库提供程序处理它,请查看”继承关系数据库“。如果模型中明确包含两个或多个继承类型,EF将仅设置继承。EF 不会扫描的基类或派生类型,可以在模型中包含类型,通过公开DbSet 继承层次结构中每个类型。不能使用数据注释来配置继承。

      

      3.1 约定

         下面示例中,有二个实体,通过公开Dbset类型,默认约定继承,如下所示:

    class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<RssBlog> RssBlogs { get; set; }
    }
    
    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
    }
    
    public class RssBlog : Blog
    {
        public string RssUrl { get; set; }
    }

        使用EF基于数据模型(Blog和RssBlog实体)创建数据库。生成后,两个实体合并到一个Blogs表中,如下所示:

        

        

      3.2  Fluent API

        如果您不想公开DbSet对于层次结构中的一个或多个实体,您可以使用Fluent API确保它们包含在模型中。如果您不依赖约定,则可以使用明确指定基类型HasBaseType。 

    class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<RssBlog>().HasBaseType<Blog>();
        }
    }

       3.3 discriminator隐藏属性

         上面3.1示例中,创建了discriminator辨别者隐藏属性,是基于base entity的层级。因为它是模型中的一个属性,所以可以像配置其他属性一样配置它。例如,要设置默认情况下的最大长度。

    modelBuilder.Entity<Blog>()
             .Property("Discriminator")
                .HasMaxLength(200);

        discriminator鉴别器也可以映射到实体中的实际CLR属性

        class MyContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Blog>()
                .HasDiscriminator<string>("BlogType");
        }
    }
    
    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }
        //discriminator
        public string BlogType { get; set; }
    }
    
    public class RssBlog : Blog
    {
        public string RssUrl { get; set; }
    }

      参考文献:

        官方文档:EF索引

               EF备用键

             EF继承

             EF继承(关系数据库)

  • 相关阅读:
    HTML DOM 06 节点关系
    HTML DOM 05 事件(三)
    HTML DOM 05 事件(二)
    HTML DOM 05 事件(一)
    html DOM 04 样式
    html DOM 03 节点的属性
    html DOM 02 获取节点
    html DOM 01 节点概念
    JavaScript 29 计时器
    JavaScript 28 弹出框
  • 原文地址:https://www.cnblogs.com/MrHSR/p/10399692.html
Copyright © 2011-2022 走看看