【问题标题】:Direct Navigation Property in Entity Framework 6Entity Framework 6 中的直接导航属性
【发布时间】:2015-03-29 04:03:35
【问题描述】:

我想实现以下目标:

public class A
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<B> Bs { get; set; }
}

public class B
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<A> As { get; set; }
}

public class C
{
    public int AID { get; set; }
    public int BID { get; set; }
    public string OtherProperty { get; set; }
}

A 和 B 很多很多,由 C 连接。但是,C 也有它自己的一些属性,这就是为什么我需要表示它。

我想从 A 直接到 Bs,而不必先经过 C。 (以及从 B 到 As)

如果 C 简单地连接 A 和 B 而没有额外的属性,这将很容易。但是因为 C 有额外的属性,我需要表示它,所以我得到了以下错误。

无法为实体集或单例“A”自动绑定实体类型“A”上的导航属性“Bs”,因为有两个或更多匹配的目标实体集或单例。匹配的实体集或单例是:B,Bs。

这是我的映射帮助...

modelBuilder.Entity<A>()
                .HasMany<B>(x => x.Bs)
                .WithMany(x => x.As)
                .Map(x =>
                    {
                        x.MapLeftKey("a_id");
                        x.MapRightKey("b_id");
                        x.ToTable("c");
                    });

【问题讨论】:

标签: c# .net entity-framework entity-framework-6 navigation-properties


【解决方案1】:

如果你想使用C,我建议你改变你的模型,如下所示:

public class A
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<C> Cs { get; set; }
}

public class B
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<C> Cs { get; set; }
}

public class C
{
    public int AID { get; set; }
    public virtual A A { get; set; }    
    public int BID { get; set; }
    public virtual B B { get; set; }

    public string OtherProperty { get; set; }
}

然后,在您的OnModelCreating 方法中,您可以这样配置CACB 之间的两个一对多关系:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Entity<C>().HasRequired(c => c.A).WithMany(a => a.Cs).HasForeignKey(c => c.AID);
     modelBuilder.Entity<C>().HasRequired(c => c.B).WithMany(b => b.Cs).HasForeignKey(c => c.BID);
}

如您所见,这最终是一个多对多关系,但现在您也在映射联结表,因为您需要在其上添加一些属性。

【讨论】:

  • 谢谢你的回答,我知道我可以通过C,但我想专门跳过它。
  • 抱歉,恐怕这是不可能的。如果向联结表添加新列,则需要一个新实体而不是直接多对多关系才能访问新列。
【解决方案2】:

如果你没有定义它,Entity Framework 只会抽象掉多对多连接表。由于您想在该连接表中添加一个属性,您(当然)需要定义该表。此时,您需要通过连接表从A 中获取您的Bs,并从B 中获取As。

另外,如果你使用C中的导航属性,你甚至不需要定义与Fluent API的关系...

public class A
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<C> Cs { get; set; }
}

public class B
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<C> Cs { get; set; }
}

public class C
{
    public int ID { get; set; }
    public virtual A A { get; set; }
    public virtual B B { get; set; }
    public string OtherProperty { get; set; }
}

如果你想强制执行唯一性...

public class C {
    [Key, Column(Order = 0)]
    public int AID { get; set; }
    [ForeignKey("AID")]
    public virtual A A { get; set; }

    [Key, Column(Order = 1)]
    public int BID { get; set; }
    [ForeignKey("BID")]
    public virtual B B { get; set; }

    public string OtherProperty { get; set; }
}

【讨论】:

  • 谢谢你的回答,我知道我可以通过C,但我想专门跳过它。
  • 您认为这会如何运作? “跳过”表格的唯一方法是在 ORM 层中将其抽象出来,这样您就不会在代码中看到它。本质上,您无法访问 ORM 层中的隐藏表。
猜你喜欢
  • 1970-01-01
  • 2014-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
相关资源
最近更新 更多