什么是独立协会和外国关键协会?

时间:2012-09-26 17:09:46

标签: c# entity-framework-4 entity-framework-5

  

可能重复:
  Code First: Independent associations vs. Foreign key associations?

在EF 4或EF 5 Code First中,什么是“独立关联”以及什么是“外键关联”,使用on MSDNForeign Key vs. Independent Relationships - is there improvement with Entity Framework 5?(强调添加):

  

2.4.1使用外键关联降低视图生成成本

     

我们已经看到了一些切换关联的案例   模型从独立协会外键关联   大大改善了视图生成所花费的时间。

所以 - 现在我知道要使用哪个。只要我知道它们是什么以及如何转换成它!那么我的问题是,您如何定义这些条款?什么流利/注释/约定会调用每个?

2 个答案:

答案 0 :(得分:35)

关于为何使用独立或外国关键协会的意见:

独立协会

优点:

  • 这是进入面向对象世界的正确方法。在面向对象的世界中,我们在聚合中使用引用,而不是一些魔术键。

缺点:

  • 使用纯POCO,您不知道主关系是否真的为NULL或者只是未加载,因为在这两种情况下您的引用都为空。您必须要求上下文在这两个空值之间有所不同。对于重EntityObject个基本实体而言,这不是一个问题,其中每个主要实体的导航属性都与另一个后缀为Reference的属性配对,提供了有关该关系的一些其他详细信息。
  • EF管理独立关联的方式非常复杂,特别是在附加分离对象图时。每个独立的关联都有自己的状态,它永远不会处于Modified状态。每次修改都包括将旧关系设置为已删除并创建添加的新关系 - 当您尝试使用它时,这是一个真正的混乱。
  • 据报道,独立协会在EF初始化期间(或在视图预生成期间)显着减慢了视图生成。
  • 在需要绑定外键的数据绑定场景中,独立关联可能更难使用。

外键关联

优点:

  • 简单。关键属性易于管理,它们解决了独立关联的所有问题 - 没有外国关联的状态,直接数据绑定,如果存在关系,则立即可见(key不为空)等。

缺点:

  • 它们在概念上是错误的并且在EF中提供它们是从对象世界到关系世界的一大步。我仍然相信正确的解决方案是改进或改变独立关联的处理方式,即使它可能导致EFv1和EFv4之间的巨大突破。我也不喜欢目前我们有两种类型的关联,行为完全不同的情况。应该只有一种类型具有明确定义的行为,并且在实体上公开了可选的外键属性。

这种差异仅适用于一对多关联,因为一对一总是外键关联,多对多总是独立关联。

答案 1 :(得分:27)

外键关联是指除了相应的导航属性之外,模型中还有外键属性的位置。独立关联是指您的数据库中有一个外键列但是与该列对应的外键属性不在您的模型中 - 即您有一个NavigationProperty但没有外键属性可以告诉您该ID的值是什么相关财产实际上没有进入相关财产。

以下是具有独立关联的模型示例(请注意,Dependent没有外键 - 只是导航属性):

public class Dependent
{
    public int Id { get; set; }

    [Required]
    public Principal PrincipalEntity { get; set; }

}

public class Principal
{
    public int Id { get; set; }
    public ICollection<Dependent> DependentEntities { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<Dependent> Dependents { get; set; }
    public DbSet<Principal> Principals { get; set; }
}

以下是相同模型的示例,但使用ForeignKey Association(注意PrincipalEntity_Id属性和[ForeignKey()]属性):

public class Dependent
{
    public int Id { get; set; }

    public int PrincipalEntity_Id { get; set; }

    [Required]
    [ForeignKey("PrincipalEntity_Id")]
    public Principal PrincipalEntity { get; set; }

}

public class Principal
{
    public int Id { get; set; }
    public ICollection<Dependent> DependentEntities { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<Dependent> Dependents { get; set; }
    public DbSet<Principal> Principals { get; set; }
}

请注意,您的数据库不会更改 - 基础数据库始终具有外键列但具有独立关联但未公开。

使用外键关联,您只需更改外键的值即可更新关系。如果您知道该值,则这很方便,因为您不需要加载要更新导航属性的实体。