【问题标题】:What does principal end of an association means in 1:1 relationship in Entity framework在实体框架中的 1:1 关系中,关联的主体端是什么意思
【发布时间】:2011-09-25 18:38:50
【问题描述】:
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 上看到了有关此错误的解决方案的问题,但我想了解“主体端”一词的含义。

【问题讨论】:

标签: c# entity-framework database-design foreign-key-relationship


【解决方案1】:

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

如果实体框架 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);

【讨论】:

  • @Ladislav,我需要创建两个独立的表,它们都可以选择相互引用(一对一),我希望它们都有自己的 PK,这怎么可能?我发布了separate question
  • 你不知道要花多少小时才能找到答案 - ms 文档太糟糕了。
  • 请注意,您可能需要使用 System.ComponentModel.DataAnnotations.Schema 添加;在VS2012中获取ForeignKey
  • 那是否意味着Foo 是当时的主体?
  • @bflemi3 你是正确的Boo 是依赖,需要一个Foo,并获取外键。 Foo 是主体,可以在没有 Boo 的情况下存在。
【解决方案2】:

你也可以使用[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; }
}

Boo 需要Foo

【讨论】:

  • 这对于我的以下代码是正确的,我希望将两者之间的映射作为单独的实体 public class Organization { public int Id { get;放; }} 公共类用户 { 公共 int Id { 获取;放; }} public class UserGroup { [Key] public int Id { get;放; } [必填] public virtual Organization Organization { get;放; } [必需] 公共虚拟用户用户 { 获取;放; } }
  • 我正在使用 Oracle 并且没有一个流利的 api 对我有用。多谢兄弟。如此简单。
  • 请注意,在使用此解决方案时,当您尝试更新刚刚从数据库中检索到的 Boo 时,您将收到验证异常,除非您首先触发 Foo 的延迟加载财产。 entityframework.codeplex.com/SourceControl/network/forks/…
  • 那么Boo Boo不应该是虚拟的吗?
  • @NathanAldenSr 现在链接坏了,你如何做出改变?
【解决方案3】:

这是参考@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;
}

现在,我们必须在 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。 WithOptionalDependent()msdn 上的描述更清楚了。

【讨论】:

  • 如果您真的想要 PrimaryBarId 属性怎么办?这对我来说很荒谬。如果我添加属性并说它是外键,则会出现错误。但如果我没有该属性,那么 EF 无论如何都会创建它。有什么区别?
  • @ChrisPratt 这听起来可能不太合理。经过反复试验,我得出了这个解决方案。当我在 PrimayBarId 实体中有 PrimayBarId 属性时,无法配置一对一映射。可能与您尝试的解决方案相同。也许是 EF 的限制?
  • 是的。我发现 EF 至今从未实现过唯一索引。因此,唯一可用的一对一映射方法是使用主端的主键作为从属端的主键,因为主键本质上是唯一的。换句话说,他们实现了一半,并采取了一条捷径,要求您的表格必须以非标准方式设计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多