2017-04-07 92 views
0

EF 6.1.3。具有组合外键的实体框架导航属性

我有一个包含许多“Header/Item”类型模式的实例的域,其中Header可以包含许多项目(1到多个),并且还包含“当前”或“最新”项目。

Header 
    Guid Id 
    Guid CurrentItemId 
    Item CurrentItem 
    ICollection<Item> AllItems 

Item 
    HeaderId 
    Id 

物品的PK总是HeaderID +的ItemID:

这表示如下。原因是,到目前为止,项目最常见的访问模式是列出与给定头相关的所有项目,并且使HeaderID成为PK /聚簇索引的第一部分意味着我们获得具有聚簇索引的数据。

我们的问题是,当我们使用CURRENTITEM导航属性,它永远只能使用项目ID做的查找,从而导致没有那么大的查询计划。

我认为这是因为我们使用CurrentItemId查找CurrentItem的约定。我的问题是,有没有办法让我告诉EF总是通过映射Header.Id,Header.CurrentItemId - > Item.HeaderId,Item.Id?来执行它对CurrentItem的连接。

我相信这是比这里所描述的略有不同的情景:composite key as foreign key

就我而言,我有一个一对一的映射不是一个顶部多了,似乎没有成为一个WithforeignKey方法可用于该场景。

+0

[复合键作为外键]的可能重复(http://stackoverflow.com/questions/5436731/composite-key-as-foreign-key) – niksofteng

+0

我不确定它是重复的,因为该帖子您引用的实体之间没有列不匹配。在我的情况下,除了映射到Item实体中的ID字段的CurrentVersionID字段之外,Header的ID字段还需要映射到Item.HeaderId字段。它也是一对一映射的情况,而不是一对多映射,并且Item实体没有导航属性返回到Header。 这可能是一个小小的差异,但它让我绊倒。 – RMD

+0

我们在一些非常类似的地方工作,但使用整数并且没有这个问题。我认为EF可能会以不同的方式处理guid,或者如果它在表上有唯一的约束,它会尝试使用它。 此外,guid可能会导致碎片问题,我知道我们在SQL Server中遇到了这个问题。 –

回答

0

我们最终没有能够得到EF生成SQL我们想要的方式 - 所以我们写了一个数据库命令截取动态发现的情况下,这种加入和重写加入符合我们设计的复合键。

我们配置此作为的DbContext水平,像这样:

this.ModifyJoin<Item, Header>(
     (i) => new Header() { CurrentItemId = i.Id }, //What to find 
     (i) => new Header() { CurerntItemId = i.Id, Id = i.HeaderId }); //What to replace with 

该信息被附加到上下文实例本身,所以当命令截取看到覆盖,它使用他们重新编写SQL。

这对于大多数场景来说结果很好,但也有一些 - 比如当作为LINQ语句的一部分在Item表上进行附加过滤时,EF使用的别名规则变得太复杂,一个完整的SQL解析器。

对于我们的使用,这导致理想的加入约90%的时间,这对我们来说已经足够好了。

完成所有这些工作的代码并不困难,但放在这里太大了。如果您想要一个副本,请添加评论,然后放在GitHub上。