2010-12-15 163 views
1

我有一个表在我的数据库中存储的项目:建模相关的实体与SQL Server和实体框架

Items 
------- 
ItemID 
Name 
... 
Etc 

和一个单独的表存储的两个不同项目的PK从第一个表。我希望能够列出一个项目,然后列出任何数量的相关项目。我试着寻找例子,但还没有发现太多令人惊讶的...

RelatedItems 
------------ 
ItemID 
RelatedItemID 

如果我有四个产品,ID分别为1,2,3和4 ...和1是与2 3我可能看起来像这样的数据:

ItemID RelatedItemID 
1  2 
1  3 
4  1 

我则模拟他们在Entity Framework设计和设计师自动添加从项目表与自身关联(多对多)。如果我在Item#1上使用第一个属性,设计师还添加了两个导航属性,我得到Item#1在第一列中的所有项目,如果使用第二个属性,则获取项目#1所在的所有项目第二列。

但是我只是想拥有一个导航属性,我可以说Items.RelatedItems并返回上述两个属性合并时的所有项目。我知道在事后我可以加入这两项结果,但我不禁认为自己做错了事,并且有更好的办法。

希望这已经足够清楚了。

回答

1

听起来像SQL模式只是不是很好的建模你正在寻找的概念。如果要建立方向关系(项目A与项目B相关,但项目B可能与项目A相关或可能不相关),那么您选择的模式将很有效。如果您正在寻找分组风格的关系(项目A和B在同一组中),我可以考虑使用不同的方法。但我想不出一种使用传统关系数据库建立固有双向关系的好方法。

一些解决方法可能是使用连接两个结果的View或使用触发器来确保从A到B的每个映射都具有从B到A的对应映射,以便这两个属性始终返回相同的物体。

0

如果你有一个项目的实例,调用它的项目,那么下面会给你相关的项目......在项目

item.RelatedItems.Select(ri => ri.Item); 

你RelatedItems属性(即你提到的第一个导航属性)将是一个RelatedItem对象的集合,每个对象都有其自己的两个导航属性,其中一个将被命名为Item,并将成为相关项目的链接。

请注意,这是空气代码,因为我不在任何可以测试此功能的前面,但我认为这将按照您的要求进行。

如果你想更简单,你可以写一个扩展方法的收官选择(),这样的事情...

public static IEnumerable<Item> RelItems(this Item item) { 
    return item.RelatedItems.Select(ri => ri.Item); 
} 

然后,你可以只是做...

item.RelItems(); 

请注意,我无法命名扩展方法RelatedItems,因为这会与EF为第二个表创建的导航属性冲突。这可能不是该表的好名字,因为它不是实际的项目,而是项目的ID。无论哪种方式,上面的代码应该工作。