在实体框架中,1:1关系中关联的主端意味着什么

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;}
}

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

无法确定类型之间关联的主要结尾 ‘ Console Application5.Boo’及‘ Console Application5.Foo’。 此关联的主体端必须使用 关系流畅的 API 或数据注释。

我已经看到过关于 StackOverflow 的问题以及这个错误的解决方案,但是我想了解术语“主要目的”是什么意思。

122720 次浏览

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

在实体框架的情况下,依赖的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 of dependent must be it's 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 ()描述更清楚。