关联的主要结尾在实体框架中以1:1的关系表示什么

tah*_*ala 266 c# database-design entity-framework foreign-key-relationship

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;}
}
Run Code Online (Sandbox Code Playgroud)

当我收到错误时,我试图在Entity Framework中执行此操作:

无法确定类型"ConsoleApplication5.Boo"和"ConsoleApplication5.Foo"之间关联的主要结束.必须使用关系流畅API或数据注释显式配置此关联的主要结尾.

我已经在StackOverflow上看到了有关此错误的解决方案的问题,但我想了解术语"主要结束"的含义.

Lad*_*nka 374

在一对一的关系中,一端必须是主要的,第二端必须是依赖的.主要末端是将首先插入的末端,并且可以在没有从属末端的情况下存在.从属端是必须在主体之后插入的端,因为它具有主体的外键.

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

public class Boo
{
    [Key, ForeignKey("Foo")]
    public string BooId{get;set;}
    public Foo Foo{get;set;}
}
Run Code Online (Sandbox Code Playgroud)

或者流畅的映射

modelBuilder.Entity<Foo>()
            .HasOptional(f => f.Boo)
            .WithRequired(s => s.Foo);
Run Code Online (Sandbox Code Playgroud)

  • 你不知道找到答案需要多少小时 - ms文档是POOOOOOP ty. (9认同)
  • @ bflemi3你是对的`Boo`是依赖的,需要一个`Foo`,并获得外键.`Foo`是校长,可以在没有`Boo`的情况下存在. (7认同)
  • @Ladislav,我需要制作两个独立的表,它们都有一个可选的引用(一对一),我希望它们都有自己的PK,这怎么可能?我发布了一个[单独的问题](http://stackoverflow.com/questions/13609507/optional-one-to-one-relationship). (4认同)
  • 那是否意味着`Foo`是校长? (2认同)

Len*_*rri 181

您还可以使用[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; }
}
Run Code Online (Sandbox Code Playgroud)

Foo是必需的Boo.

  • 请注意,在使用此解决方案时,当您尝试更新刚刚从数据库中检索到的"Boo"时,您将获得验证异常,除非您首先触发`Foo`属性的延迟加载.https://entityframework.codeplex.com/SourceControl/network/forks/BrandonDahler/EntityFramework/contribution/7703 (10认同)
  • 在SO上找到了几个答案 - 这是最好最简单的! (3认同)
  • 在此工作之前,我不得不重建我的项目. (2认同)
  • 那么“ Boo Boo”不应该是虚拟的吗? (2认同)

Sud*_*SMD 8

这是参考@Ladislav Mrnka关于使用流畅的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;
}
Run Code Online (Sandbox Code Playgroud)

现在,我们必须在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;
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用流畅的api指定一对一关系:

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

请注意,虽然PrimaryBarId需要删除添加,但我们通过流畅的api指定它.

另请注意,方法名称[WithOptionalPrincipal()][1]具有讽刺意味.在这种情况下,Principal是Bar.msdn上的WithOptionalDependent()描述使其更加清晰.

  • 如果您确实*想要'PrimaryBarId`属性怎么办?这对我来说太荒谬了.如果我添加属性并说它是外键,我会收到错误.但如果我没有这个属性,那么EF无论如何都会创建它.有什么不同? (2认同)
  • 是啊,就是.我发现EF到今天从未实现过独特的索引.因此,可用于映射一对一的唯一方法是使用主端的主键作为从属端的主键,因为主键本质上是唯一的.换句话说,他们半实现了它,并采用了一种捷径,规定你的表必须以非标准的方式进行设计. (2认同)