1. 多对多的关系
1.1情况1:
表之间存在多对多的关系时,使用一个中间关系表,来保存各表之间的关系。如下图所示:
每个Member和Goods之间是多对多的关系,并通过一个中间表来存储他们之间的关联。通过模型生成向导,最后生成的实体模型如下所示:
如上图所示,EF在生成实体模型时,对于仅仅只保存关系的中间表,是不会单独生成一个实体的,而是生成一个*…*的关系来表示。并且,可以看到,各个实体均有可以导航到关联实体的导航属性。生成实体模型之后,我们就可以编写如下访问代码:
using (var db = new ExampleEFEntities())
{
var m = new Members() { Age = 123, Email = "123@mail.com", Name = "321", PassWord = "123" };
var g1 = new Goods() { GoodsName = "Computer", GoodsPrice = 3210 };
var g2 = new Goods() { GoodsName = "Mobile", GoodsPrice = 1230 };
m.Goods.Add(g1);
m.Goods.Add(g2);
db.Members.AddObject(m);
db.SaveChanges();
}
通过代码,我们只是添加了几个关联的数据,而没有去写添加中间关系的代码。执行代码之后,可以看到实体模型会自动将新的数据记录之间的关系保存到数据库中对应中间关系表中。EF为我们很好的处理这种表之间的关系,方便我们对各个表的之间操作。
1.2 情况2:
表之间存在多对多的关系时,使用一个中间关系表,来保存各表之间的关系,同时关系表还存在着其他的字段保存相关的数据信息。例如,如下图所示:
每个Member和Goods之间是多对多的关系,并通过一个中间表来存储他们之间的关联,此外关系表还存在保存相关的数据信息字段。通过模型生成向导,最后生成的实体模型如下所示:
注意:如果中间没有设置主键,那么在插入数据的时候,会出现如下错误:
因为它有一个 DefiningQuery,而 <ModificationFunctionMapping> 元素中没有支持当前操作的 <InsertFunction> 元素。
如上图所示,EF对于这种非仅仅只保存关系的中间来,他是会生成一个实体与之对应。然后,我们可以通过如下代码示例来访问数据库:
using (var db = new ExampleEFEntities())
{
var m = new Members() { Name = "ef4", Email = "ef4@mail.com", PassWord = "123" };
var g = new Goods() { GoodsName = "Car", GoodsPrice = 123123 };
var mg = new MemberGoods() { Goods = g, Members = m, TotalPrice = 123123 };
m.MemberGoods.Add(mg);
db.Members.AddObject(m);
db.SaveChanges();
}
对于这种情况,在设置关系就需要我们去处理各实体之间的关系。
2.自关联的关系
很常见的一种情况,自关联的表。就是存在自己关联自己的表结构,比如:树。如下所示:
使用EF模型生成向导,最终生成的模型如下图所示:
对于自关联的表,EF会生成一个实体,并同时有导航到父和子实体的导航属性。(导航属性的名称默认可不是Child或者Parent,我们可以在导航属性的属性窗口,根据关系类型,修改成一个容易明白名称,如上图所示)。
这样,我们就可以很容易对种存在树形结构的表进行操作了,如下所示:
using (var db = new ExampleEFEntities())
{
var root = new Tree() { TreeId = 1, TreeName = "董事会" };
var child1 = new Tree() { ParentTree = root, TreeName = "总经办", TreeId = 2 };
var child2 = new Tree() { ParentTree = child1, TreeName = "各部门", TreeId = 3 };
db.Tree.AddObject(root);
db.SaveChanges();
}
在代码中,我们只需要给对应的ParentTree或ChildTree赋值,那么他们直接的父、子关系就可以正确的保存到数据库中了。相比以前写存储过程、递归来操作这种树型结构,确实方便了很多。