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索引
最新文章
- Android历史版本Logo
- 为了防止采集,把文章中出现的URL链接随机大小写(PHP实现)
- Java SE 第十六讲----方法重载
- 【Python】菜鸟的基本课程继续中
- Windows Live Writer针对CNBLOG的代码高亮插件
- vuex的简易入门
- ltp-ddt nor_mtd_dd_rw_jffs2
- windows下python操作mysql模块安装
- restore not found的错误
- opencv学习之路(10)、ROI与mask掩码
- git别名;git配置使用shell函数;git别名使用shell函数;git获取当前分支;git alias
- ava中有三种移位运算符
- python ros 订阅robot_pose获取机器人位置
- jquery的liveQuery插件
- Generic/Template Programming in Flink
- python中如何退出多层循环
- c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)
- 原创:解决 python中moviepy调用ffmpeg的错误:subprocess, PermissionError: [WinError 5] 拒绝访问
- DB2常用函数详解
- Oracle Business Intelligence Enterprise Edition 12.2.1.2.0 Books
热门文章
- 决AndroidStudio 安卓模拟器安装在D盘问题
- SQL server 查询出现:---“子查询返回的值不止一个。当子查询跟随在 =、!=、<;、<;=、>;、>;= 之后,或子查询用作表达式时,这种情况是不允许的。”SQL查询错误解析---
- 什么是布局?Android中的布局是怎样的?
- ubuntu的安装及ubuntu中安装mysql和tomcat
- Java String类的intern()方法
- Rectangular Covering [POJ2836] [状压DP]
- Debug命令详解
- VB洗牌算法产生随机数组
- redis的过期策略都有哪些?
- SCOPE_IDENTITY() 和 @@identity