public class Foo
{
    public string FooId{get;set;}
    public Boo Boo{get;set;}
}


public class Boo
{
    public string BooId{get;set;}
    public Foo Foo{get;set;}
}

当我得到错误时,我试图在实体框架中这样做:

无法确定类型之间关联的主端 “ConsoleApplication5。Boo'和'ConsoleApplication5.Foo' 属性显式配置此关联的主体端 关系流畅API或数据注释。

我在StackOverflow上看到了这个错误的解决方案,但我想了解术语“principal end”是什么意思。


在一对一的关系中,一端必须是主的,另一端必须是从属的。主端是最先插入的端,并且可以在没有从属端的情况下存在。依赖端必须插入到主体之后,因为它有指向主体的外键。

在实体框架的情况下,依赖的FK也必须是它的PK,所以在你的情况下,你应该使用:

public class Boo
{
    [Key, ForeignKey("Foo")]
    public string BooId{get;set;}
    public Foo Foo{get;set;}
}

或者流畅映射

modelBuilder.Entity<Foo>()
            .HasOptional(f => f.Boo)
            .WithRequired(s => s.Foo);

你也可以使用[Required]数据注释属性来解决这个问题:

public class Foo
{
    public string FooId { get; set; }

    public Boo Boo { get; set; }
}

public class Boo
{
    public string BooId { get; set; }

    [Required]
    public Foo Foo {get; set; }
}

Foo是Boo所必需的。


这是参考@Ladislav Mrnka关于使用fluent api配置一对一关系的回答。

有一种情况,依赖的FK必须是它的PK是不可行的。

例如,Foo已经和Bar有一对多的关系。

public class Foo {
   public Guid FooId;
   public virtual ICollection<> Bars; 
}
public class Bar {
   //PK
   public Guid BarId;
   //FK to Foo
   public Guid FooId;
   public virtual Foo Foo;
}

现在,我们必须在Foo和Bar之间添加另一个一对一的关系。

public class Foo {
   public Guid FooId;
   public Guid PrimaryBarId;// needs to be removed(from entity),as we specify it in fluent api
   public virtual Bar PrimaryBar;
   public virtual ICollection<> Bars;
}
public class Bar {
   public Guid BarId;
   public Guid FooId;
   public virtual Foo PrimaryBarOfFoo;
   public virtual Foo Foo;
}

下面是如何使用fluent api指定一对一的关系:

modelBuilder.Entity<Bar>()
            .HasOptional(p => p.PrimaryBarOfFoo)
            .WithOptionalPrincipal(o => o.PrimaryBar)
            .Map(x => x.MapKey("PrimaryBarId"));

请注意,在添加PrimaryBarId时需要删除,因为我们通过fluent api指定它。

还要注意方法名[WithOptionalPrincipal()][1]有点讽刺。在本例中,Principal是Bar。msdn上的WithOptionalDependent()描述使其更加清晰。