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索引
上一篇: 千万别抠门
下一篇: 你看到我的另一只鞋了吗?