需要澄清实体框架代码优先和导航属性和标量密钥

时间:2012-10-07 04:23:45

标签: entity-framework data-annotations fluent-interface

据我了解(所以如果我弄错了请纠正我),可以用几种方式定义它们之间有关系的实体类 - (1)通过使用两个属性来表示标量键加上导航属性或(2)只使用导航属性。

如果您使用数据注释我相信您唯一的选择是同时使用标量键和导航属性,而使用Fluent API这两种方法都可用。

我的问题是采取哪种方法?各自的优点和缺点是什么? (这是关于外键和导航属性的两个选择... 关于数据注释与流利。

我认为可以归结为这些因素/关注

  1. 同时拥有标量属性和导航属性可能会被视为“弄脏”该类。
  2. 只有导航属性需要通过Includes()调用才能访问FK值。我没有查看正在发送的SELECT语句,但我怀疑正在执行JOIN并且正在发回不需要的数据。
  3. 拥有标量属性将排除对Include()调用的需要。
  4. 正如我之前提出的SO问题(related question)暗示的那样,导航属性看起来不能用作复合键的一部分,因此会强制包含额外的标量键。如果您必须为一个属性执行此操作,那么在所有类中保持一致是有意义的。
  5. 我错过了什么吗?一般来说,定义外键和导航属性的推荐方法是什么?为什么甚至提供两种方法,因为它似乎混淆了水域?我看了很多教程,看到了两种方法的混合。

    谢谢。

1 个答案:

答案 0 :(得分:1)

  

(1)通过使用属性来表示标量键加上导航属性,或者(2)使用导航属性。

这是foreign key and independent associations之间的区别。

  

如果您使用数据注释我相信您唯一的选择是使用标量键和导航属性,而使用Fluent API这两种方法都可用。

没有。数据注释只是另一个提示。默认约定会自动识别导航属性。

  

同时拥有标量属性和导航属性可能会被视为“弄脏”该类。

是的但由于具有标量属性的两种关联类型的不同性质使得一些开发任务更简单。

  

只有导航属性需要通过Includes()调用才能访问FK值。我没有查看正在发送的SELECT语句,但我怀疑正在执行JOIN并且正在发回不需要的数据。

是。 Include表示获取数据,但如果只需要在linq-to-entities查询中访问FK,则无需使用它。例如:

 var children = from c in context.Children
                where c.Parent.Id == 123
                select c;

此查询通过Parent访问“FK”并在内部生成连接但不提取父级。

  

拥有标量属性将排除对Include()调用的需要。

没有。 Include依赖于导航属性,而FK属性本身不会创建关联。您始终必须在关系的至少一侧具有导航属性(在我的示例中为ParentChild)。

  

看起来导航属性不能用作复合键的一部分

是。如果需要复合键,则需要在实体上公开外键。

additional related question