【问题标题】:Using both many-to-many and one-to-many to same entity对同一实体使用多对多和一对多
【发布时间】:2011-11-22 15:04:07
【问题描述】:

我在 EF Code-First 中有一个多对多关联(如this 问题中所述),我也想对同一个实体使用一对多。问题是 EF 没有生成正确的数据库方案。代码:

public class A
{
  public int Id { get; set; }
  public string Name { get; set; }
  public virtual ICollection<B> ObjectsOfB { get; set; }
}

public class B
{
  public int Id { get; set; }
  public virtual A ObjectA { get; set; }
  public virtual ICollection<A> OtherObjectsOfA { get; set; }
}

当我删除 B 类的 ObjectA 属性时,会正确生成多对多关联。 如果生成不正确,实体 B 会获得 A 的 2 个外键,而实体 A 会获得 B 的 1 个外键(类似于多对一关系)。

【问题讨论】:

    标签: c# entity-framework many-to-many one-to-many


    【解决方案1】:

    如果你有多个导航属性引用同一个实体,EF 不知道另一个实体上的反向导航属性属于哪里。在您的示例中:A.ObjectsOfB 是指B.ObjectA 还是B.OtherObjectsOfA?两者都是可能的并且是一个有效的模型。

    现在,EF 不会抛出“无法明确确定关系”之类的异常。相反,它决定B.ObjectA 引用B 中的第三个端点,该端点未作为模型中的导航属性公开。这将在表B 中创建第一个外键。 B 中的两个导航属性引用 A 中的两个端点,它们也未在模型中公开:B.ObjectA 在表 B 中创建第二个外键,B.OtherObjectsOfA 在表 @987654332 中创建外键@。

    要解决此问题,您必须明确指定关系。

    选项一(最简单的方法)是使用InverseProperty 属性:

    public class A
    {
        public int Id { get; set; }
        public string Name { get; set; }
        [InverseProperty("OtherObjectsOfA")]
        public virtual ICollection<B> ObjectsOfB { get; set; }
    }
    

    这定义了A.ObjectsOfB 是与B.OtherObjectsOfA 的多对多关系的一部分。

    另一种选择是在 Fluent API 中完全定义关系:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<A>()
            .HasMany(a => a.ObjectsOfB)
            .WithMany(b => b.OtherObjectsOfA)
            .Map(x =>
            {
                x.MapLeftKey("AId");
                x.MapRightKey("BId");
                x.ToTable("ABs");
            });
    
        modelBuilder.Entity<B>()
            .HasRequired(b => b.ObjectA)  // or HasOptional
            .WithMany()
            .WillCascadeOnDelete(false);  // not sure if necessary, you can try it
                                          // without if you want cascading delete
    }
    

    【讨论】:

    • 感谢您的回答!但是,对于这两种解决方案,我都会遇到以下异常:A first chance exception of type 'System.InvalidOperationException' occurred in EntityFramework.DLL
    • 更正:流利的解决方案有效(我的错误..),非常感谢!知道为什么InverseProperty 会引发异常吗?
    • @Henkie:应用程序真的崩溃了吗? “第一次机会异常”通常不是问题,仅显示在调试器输出窗口中。一般可以忽略。
    • 应用程序确实没有崩溃,但没有生成数据库方案。我正在使用 VS Express,所以我不能在第一次机会异常时中断。
    • [InverseProperty] 标签对我来说就像一个魅力,非常感谢!
    【解决方案2】:

    如果表 B 具有表 A 的外键,则类 B 具有指向 A 的导航属性,而 A 具有指向 ICollection&lt;A&gt; 的导航属性。
    如果表 B 与表 A 有多对多关系,则 A 类必须有 ICollection&lt;B&gt;,B 类必须有 ICollection&lt;A&gt;

    试试看,也许这会澄清你对 EF 的要求。

    【讨论】:

    • 在我的代码示例中,我忘记将 ICollection 添加到 class A 以实现多对多关联。现在已经修好了。
    • @Henkie:很高兴我能帮上忙 :)
    猜你喜欢
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 2014-08-15
    相关资源
    最近更新 更多