实体框架与同一实体的代码优先,一对零一对一和一对多关系

问题描述:

我正在使用Entity Framework v6.0创建代码优先的数据库.我在c#中定义了一个 Organization 类和一个相关的 Location 类,如下所示:

I'm creating a code-first database with v6.0 of the Entity Framework. I have an Organisation class and a related Location class defined in c# as follows:

public class Organisation
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Location> Locations { get; set; }

    public int? HQLocationId { get; set; }
    public Location HQLocation { get; set; }
}

public class Location
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int OrganisationId { get; set; }
    public Organisation Organisation { get; set; }
}

从课程中可以推断,一个组织可以有多个位置,但是它只能有一个总部位置.

As can be inferred from the classes, an Organisation can have multiple Locations, however it can only have one Head Quarters Location.

我正在使用Fluent API来配置这些类之间的关系. 多个位置"方面非常简单,可用于以下方面:

I'm using the Fluent API to configure the relationships between these classes. The "multiple locations" aspect is simple enough and works with the following:

   HasMany(o => o.Locations)
      .WithRequired(o => o.Organisation)   
      .HasForeignKey(l => l.OrganisationId);

但是,我似乎找不到正确的语法来定义允许定义总部位置的关系.如果我采用的方法存在缺陷,还是我只是缺少正确的语法?

I cannot however seem to find the correct syntax to define the relationship that allows the HQ location to be defined. If there a flaw in the approach I'm taking, or am I simply missing the right syntax?

更新

如果我在组织配置中添加以下内容:

If I add the following to the Organisation configuration:

   HasOptional(o => o.HQLocation)
      .WithMany()
      .HasForeignKey(o => o.HQLocationId)
      .WillCascadeOnDelete(true);

然后实体框架不再出错,并且我的数据以适合我需要的形状加载.

Then Entity Framework no longer errors and my data loads in a shape that suits my needs.

但是,这允许将位置用作多个组织总部;理想情况下,我不希望这样做.

However this allows a Location to be the HQ for more than one Organisation; which ideally I do not want possible.

一对一一对零或一个关系中Id在两个实体上都相同.这意味着Organisation.Id必须与HQLocationLocation.Id相同.当然,这不是一个好的设计选择.我建议向Location添加属性以指示它是否为HQLocation:

In one-to-one or one-to-zero or one relationships Id should be same on both entities. This means that Organisation.Id must be same as Location.Id for HQLocation. And of course, it is not good design choice. What I recommend is to add property to Location to indicate whether it is a HQLocation or not:

public class Organisation
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Location> Locations { get; set; }
}

public class Location
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsHqLocation { get; set; }

    public int OrganisationId { get; set; }
    public Organisation Organisation { get; set; }
}