17

< RANT_MODE >

EF 代码优先方法旨在节省大量时间,但目前我只看到玩具示例并花费数小时试图了解如何使其生成我想要的数据库。但仍然希望尤里卡时刻:-)

< RANT_MODE />

关于问题!

虚拟与具体属性

我试图了解 EF 如何映射和检索对象关系。我应该什么时候标记一个属性virtual,什么时候不?(如在public Person Owner { get; set; }vs.中public virtual Person Owner { get; set; }。)在我见过的数十个代码优先示例中,他们似乎可以互换使用这些示例,但没有太多解释。我所知道的是导航属性 ( public virtual ICollection<Person> Owners { get; set; }) 必须是virtual为了使延迟加载成为可能(正确..?),但这在非收藏品世界中如何应用?

对象关系和外键

public int OwnerId { get; set; }除了我感兴趣的“主要”属性()之外,我找不到任何关于是否应该包含外键字段( )的信息public Person Owner { get; set; }。我尝试不这样做,并且 EF 友好地自动添加了一个 int 列Owner_Id在我的表中命名,似乎理解我想要实现的目标。

Code First 的约定(“外键”部分)中,EF 团队提到“在关系的依赖端包含外键属性是很常见的”,并且“Code First 现在会推断出任何名为 '' (即 OwnerId)[...] 具有与主键相同的数据类型,表示关系的外键”。IE。如果我有两个 EF 就会知道它们是相关的。

但是,除了“外来对象”本身之外,明确指定持有 FK 的此类属性是否被认为是一种好的做法?

外来对象、外键 - 续

正如我上面提到的,即使我只有public Person Owner { get; set; }在我的对象中(比如Event),该表Events也会包含一个Owner_Id由 EF 自动添加的列。更重要的是,检索后我将可以访问Owner.

但是,请考虑以下情况。我有两个课程:

public class Account
{
    public int Id { get; set; }
    public Person Owner { get; set; }
}

public class OpenIdAccount : Account
{
    public string Identifier { get; set; }
}

我希望它们与 TPT 相关。这意味着手动映射:

modelBuilder.Entity<Account>().MapHierarchy(a => new
{
    a.Id, 
    Owner_Id = a.Owner.Id
}).ToTable("Account");

modelBuilder.Entity<OpenIdAccount>().MapHierarchy(a => new
{
    a.Id,
    a.Identifier
}).ToTable("OpenIdAccount");

您可能会注意到,我试图重新创建 EF 对我的Owner_Id专栏所做的事情。然而在检索时,myAccountInstanceFromDb.Owner为空。这是为什么?我如何告诉 EF 它应该发挥它的魔力并填充我的Owner财产?

指针,指针

如果您能澄清上述内容,我将不胜感激 - 达到了真正希望知道答案的地步,但无法阅读另一篇文章,该文章仅展示了另一个玩具示例,说明使用 EF 是多么容易。也就是说,如果您确实对 EF 的大脑有深入的最新参考,请也发布链接。

提前感谢您的宝贵时间!

4

2 回答 2

9

虚拟与最终属性:

这实际上与代码无关,这是 EF 和 POCO 的主题:当您拥有 POCO 时,您会失去对导航属性的大量 EF 支持,您可以通过将它们设为虚拟来选择加入它们。这允许 EF 在运行时创建代理,并通过覆盖该代理类中的导航属性为您提供支持。这些支持是更改通知关系修复延迟加载

延迟加载对 Collection 和非 Collection 类型的导航属性的工作方式相同。此外,始终将导航属性标记为虚拟也是一种很好的做法。

外键关联或独立关联

EF3.5 不支持关联中的 FK 并将其隐藏(也称为独立关联)。EF4 开始支持关联中的 FK(又名外键关联)。取决于您喜欢哪一个,您可以显式包含或不包含 FK 属性,但除了导航属性之外,显式指定 FK 属性绝对是一种好习惯,因为它为您提供了使用对象的最大灵活性。

检索后,myAccountInstanceFromDb.Owner 为空。这是为什么?我如何告诉 EF 它应该发挥它的魔力并填充我的 Owner 属性?

当然,您没有将其标记为虚拟,因此不支持延迟加载,但您也没有明确地预先加载或延迟加载它。要解决此问题,请使用virtual关键字并让 EF 为您延迟加载它,或者使用Include方法在整个对象物化时预先加载它。

标量属性与导航属性

标量属性是其值包含在实体中并与表列相对应的属性(例如 Account.Id)。
导航属性只是指向相关实体的指针。例如,Account 实体有一个 Owner 属性,该属性将使应用程序能够从一个 Account 导航到拥有该 Account 的 Owner。
因此,回到您的问题,您需要做的就是将导航属性指定为virtual Person Owner并可选择指定 FK 属性为int OwnerId,您就可以开始了。

于 2010-11-26T04:54:26.157 回答
0

将属性标记为虚拟会使相关对象延迟调用

您无需添加外键字段 public Person Owner { get; 放; } 将添加一个外键映射

于 2010-11-26T01:39:11.570 回答