在数据库设计中,有时会发现,数据库中的表格与应用程序所需的实体并不完全匹配。可能的情况是,数据库中的表格数量要么过多,要么过少,不符合应用程序逻辑上对实体的需求。另一种情况是,虽然每个逻辑实体都对应一个表格,但它们之间的关系从应用程序和实体的角度来看并不合逻辑。Entity Framework中的继承机制提供了一种方法,可以创建所需的逻辑实体来操作一组数据库表格,并且还可以利用继承关系创建更有意义的实体之间的关系。
Entity Framework中存在三种类型的继承关系:每类型表格(Table per Type, TPT)、每层次表格(Table per Hierarchy, TPH)和每具体类型表格(Table per Concrete Type, TPC)。本文将尝试探讨每类型表格继承关系,因为从效率角度来看,这种方式相对更为高效,并且可以很好地模拟具有一对一关系的表格。
当有多个表格通过外键约束具有一对一关系时,TPT关系特别有用。如果为这些表格创建实体,Entity Framework将生成默认的实体,这些实体具有一对一的关系,而使用继承关系可以更好地建模这些关系。
让通过一个简单的例子来理解这个概念。假设有一个表格用来跟踪“自行车”数据。这个表格将记录商店中所有的自行车。现在商店还有两个额外的表格用于“二手自行车”和“打折自行车”。它们与原始自行车表格之间建立了外键关系。从应用程序的角度来看,所有的“二手自行车”和“打折自行车”也都是自行车。这意味着它们之间存在逻辑上的继承关系。
为了创建继承关系,需要删除实体之间的现有关系,并在它们之间添加继承关系(这可以通过在实体设计器上右键点击来完成)。在进行这些更改后,实体之间的继承关系将如下所示:
如果希望“自行车”表中的所有实体都是“二手自行车”或“打折自行车”,需要将“自行车”实体标记为抽象的。目前,让保持可以创建“自行车”实体的可能性,即它不是抽象的。
现在有了具有一些逻辑关系的实体,并且准备好使用这些实体了。让现在看看如何对这些相关实体执行各种CRUD操作,这将反过来更新相应的表格。
插入操作:让从插入操作开始。让看看如何将实体添加到“二手自行车”实体:
string name = txtNameP.Text;
string manf = txtManfP.Text;
int years = Convert.ToInt32(txtYearsP.Text);
using (BikeDbEntities entities = new BikeDbEntities())
{
PreOwnedBike bike = new PreOwnedBike { BikeName = name, Manufacturer = manf, YearsOld = years };
entities.AddToBikes(bike);
entities.SaveChanges();
Response.Redirect("Default.aspx");
}
在这里,从用户那里获取输入,然后创建一个“二手自行车”对象。然后将其添加到实体的“自行车”集合中(由于有继承关系,所有的“二手自行车”都是自行车,因此这个调用将负责在相应的表格中插入所有数据)。
同样,也可以插入到“打折自行车”表中。
选择操作:要从表中选择数据,可以从表中选择所有数据,或者可以指定选择标准来选择表中的数据。要从相应的表格中选择所有数据,只需要使用Context类集合属性。
// 获取自行车
GridView1.DataSource = entities.Bikes;
GridView1.DataBind();
// 获取二手自行车
GridView2.DataSource = entities.Bikes.OfType
如果需要使用一些搜索标准来选择“自行车”的类型,可以从“自行车”集合中获取结果,并使用typeof操作符检查实体的实际类型。
更新和删除:要更新记录,首先需要确定自行车的实际类型,可以通过使用typeof操作符来做到这一点,然后可以像处理普通实体一样更新自行车的属性。
int id = Convert.ToInt32(TextBox1.Text);
using (BikeDbEntities entities = new BikeDbEntities())
{
Bike bike = entities.Bikes.SingleOrDefault
在上面的代码中,直接更新了与基实体相关的详细信息,并且为了更新与派生实体相关的详细信息,首先通过检查typeof来转换类型,然后更改实体的属性。
删除操作也将遵循相同的理念,它不会更新记录,而是简单地从表中删除记录。
int id = Convert.ToInt32(TextBox1.Text);
using (BikeDbEntities entities = new BikeDbEntities())
{
Bike bike = entities.Bikes.SingleOrDefault
执行上述所有操作将更改相应表中的数据,并且还会处理表格之间的参照完整性。