31

我有两节课。如何使用实体框架代码优先方法将这两个类变成一对一的关系?

public class Region
{
  public int RegionId { get; set; }
  public string Name { get; set; }

  public virtual Factory _factory { get; set; }
}

public class Factory
{
  public int FactoryId { get; set; }
  public string Name { get; set; }

  public virtual Region _region { get; set; }
}

当我尝试这个时,我得到这个错误:多重性在关系'Region_Factory'中的角色'Region_Factory_Source'中无效。因为从属角色属性不是关键属性,所以从属角色的多重性的上限必须是“*”。

4

2 回答 2

40

由于 virtual 关键字,这发生在 CodeFirst 中。实际上,您正在创建一种关系,其中创建一个项目需要创建另一个项目。但是,virtual 关键字允许延迟实例化,这意味着创建一种类型的对象不会自动创建另一种类型,从而允许外来项上的 Id 为空。这意味着 0..1 关系,但由于每一面都是虚拟的,所以你得到的是 0..0,这是不允许的。

您可以使用 2 种方法来纠正这种情况。

  1. 从导航属性的一侧或两侧删除虚拟选项,允许使用 0..1 或 1..1 地图。
  2. 从每个对象的其他实体显式添加外键属性。即在类上Region添加一个属性,FactoryId并在Factory添加一个属性RegionId

还有其他方法可以帮助 Entity Framework 确定哪个对象是 Dependent Object,即使用 Entity Framework Fluent api。

来自MSDN

配置两端都需要的关系(一对一)

在大多数情况下,实体框架可以推断出关系中的依赖类型和主体类型。但是,当关系的两端都是必需的或双方都是可选的时,实体框架无法识别依赖者和主体。当关系的两端都需要时,在 HasRequired 方法之后使用 WithRequiredPrincipal 或 WithRequiredDependent。当关系的两端都是可选的时,在 HasOptional 方法之后使用 WithOptionalPrincipal 或 WithOptionalDependent。

以下代码将创建一个 PrincipalFactory和一个 DependentRegion

// Configure the primary key for the Region
modelBuilder.Entity<Region>()
    .HasKey(t => t.RegionId);

modelBuilder.Entity<Factory>()
    .HasRequired(t => t.Region)
    .WithRequiredPrincipal(t => t.Factory);
于 2013-09-10T18:10:15.973 回答
5

EF6,添加属性:

[Key]
public int RegionId { get; set; }

[Key, ForeignKey("Region")]
public int FactoryId { get; set; }
于 2016-07-19T19:09:06.860 回答