EF6 秘籍 2th:实体数据建模基础 (七)建模有标量属性的多对多关系
问题:
在数据库的链接表中除了原有的外键列之外,还有其他的数据列。现在想把链接表及其关联表导入到EDM中,以形成一个多对多关系或2个一对多关系。
解决方案:
EF不支持带有属性的关联。如果链接表包含有除了外键之外的其他列,EF将产生一个单独的实体类型以表示这个链接表。最终的模型将包含一个链接表实体类型和2个一对多的关联。
数据库图表如下:
数据库脚本如下:
use[EF6Recipes]gocreatetableChapter2.Item(SKUintprimarykey,[Description]varchar(50)notnull,Pricedecimal(18,2)notnull);createtableChapter2.[Order](OrderIdintidentityprimarykey,OrderDatedatetimenotnull);createtableChapter2.OrderItem(OrderIdintforeignkeyreferencesChapter2.[Order](OrderId),SKUintforeignkeyreferencesChapter2.Item(SKU),[Count]intnotnull,constraintPK_OrderItemprimarykey(OrderId,SKU));
一个订单(Order)能有多个项(Item),一个项也能包含在多个订单里。另外,还有一个Count属性关联到每个订单与项的实例。这个Count属性就被称为负载(Payload)。
操作步骤同EF6 秘籍 2th:实体数据建模基础 (五)从现有数据库生成模型一致,不再重复。
生成的EDM如下图:
原理:
EF不支持带有其他属性列的关联。它将转换这个链接表为一个包含2个一对多关联的实体。在这种情况下,OrderItem表没有被转换成一个关联,而是转换为一个1对多关联到Order和一个1对多关联到Item的实体类型。
额外属性列的增加需要关联表的实体提供一个额外的跳板以获取相关的项。
using(varcontext=newEF6RecipesContext()){varoiList=newList<OrderItem>();varorder1=newOrder{OrderDate=newDateTime(2010,1,18)};varorder2=newOrder{OrderDate=newDateTime(2010,1,19)};varitem1=newItem{SKU=1729,Description="Backpack",Price=29.97M};varitem2=newItem{SKU=2929,Description="WaterFilter",Price=13.97M};varitem3=newItem{SKU=1847,Description="CampStove",Price=43.99M};oiList.Add(newOrderItem{Order=order1,Item=item1,Count=1});oiList.Add(newOrderItem{Order=order1,Item=item2,Count=3});oiList.Add(newOrderItem{Order=order1,Item=item3,Count=1});oiList.Add(newOrderItem{Order=order2,Item=item1,Count=2});oiList.Add(newOrderItem{Order=order2,Item=item2,Count=2});oiList.Add(newOrderItem{Order=order2,Item=item3,Count=2});context.OrderItems.AddRange(oiList);context.SaveChanges();}using(varcontext=newEF6RecipesContext()){foreach(varorderincontext.Orders){Console.WriteLine("Order#{0},orderdon{1}",order.OrderId,order.OrderDate.ToShortDateString());Console.WriteLine("SKU\tDescription\tQty\tPrice");Console.WriteLine("---\t-----------\t---\t-----");foreach(varoiinorder.OrderItems){Console.WriteLine("{0}\t{1}\t{2}\t{3}",oi.SKU,oi.Item.Description,oi.Count,oi.Item.Price);}}}
运行结果如下:
该代码与原文提供的程序不一样,原文提供的代码我执行的时候只插入了Order的数据,附原文代码:
varorder=newOrder{OrderId=1,OrderDate=newDateTime(2010,1,18)};varitem=newItem{SKU=1729,Description="Backpack",Price=29.97M};varoi=newOrderItem{Order=order,Item=item,Count=1};item=newItem{SKU=2929,Description="WaterFilter",Price=13.97M};oi=newOrderItem{Order=order,Item=item,Count=3};item=newItem{SKU=1847,Description="CampStove",Price=43.99M};oi=newOrderItem{Order=order,Item=item,Count=1};context.Orders.Add(order);context.SaveChanges();
最佳实践:
由于链接表有负载和没有负载,生成的模型完全不同。这就需要我们在设计之初就需要分析链接表会不会有其他列的可能,如果不能确定,使用一个自增列。这样的话就会生成一个包含2个1对多关系的实体类型。在以后进行其他属性列扩展时,对模型的影响最小。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。