实体框架代码优先导航问题

Posted

技术标签:

【中文标题】实体框架代码优先导航问题【英文标题】:Entity Framework Code First navigation issue 【发布时间】:2011-04-05 04:42:42 【问题描述】:

我正在尝试设置一个导航属性,该属性将包含另一个表格的零个或多个元素。 Entity Framework 似乎遇到的问题是另一个表有一个复合主键。

public class Alpha

    public int Id  get; set; 
    public int? BetaId  get; set; 
    public virtual ICollection<Beta> Beta  get; set; 
    public string Name  get; set; 


public class Beta

    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id  get; set; 
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int SequenceNumber  get; set; 
    public string Name  get; set; 


public class ABContext : DbContext

    public DbSet<Alpha> Alpha  get; set; 
    public DbSet<Beta> Beta  get; set; 

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        modelBuilder.Entity<Beta>()
            .HasKey(b => new  b.Id, b.SequenceNumber );
    

我不确定如何正确设置关系。我尝试了几种不同的方法。 Entity Framework 要么抱怨没有使用 Beta 类中的两个键来定义导航属性,要么在 Alphas 表中创建了一对未正确链接表的额外列。

目标是 Alpha 应持有一组基于 Beta.Id 的零个或多个 Beta。一个 Beta 可能属于零个或多个 Alpha。但是,我对 Beta 与 Alpha 的关系并不真正感兴趣。

有什么想法吗?

【问题讨论】:

为什么不使用 [Key] 属性指定您的密钥?而且即使你不感兴趣,将 Alpha 属性添加到 Beta 中也不会伤害任何人。 我可以使用[Key, Column(Order = #), ...],但它的作用与.HasKey() 完全相同。将public virtual ICollection&lt;Alpha&gt; Alpha get; set; 添加到类 Beta 会创建一个 BetaAlphas 查找表。我只想设置 Alpha.BetaId 并自动获取 Beta 集合。 【参考方案1】:

让我们来看看你的要求:

Alpha 应该包含零个或多个 Beta 的集合 .... 一个 Beta 可能属于零个或多个 Alpha

这是多对多的关系,所以你必须映射它。

protected override void OnModelCreating(DbModelBuilder modelBuilder)

    modelBuilder.Entity<Beta>()
        .HasKey(b => new  b.Id, b.SequenceNumber );

    modelBuilder.Entity<Alpha>()
        .HasMany(a => a.Beta)
        .WithMany();

这将在数据库中创建具有三列的附加表(可能称为 Alpha_Id、Beta_Id 和 Beta_SequenceNumber)。

我仍然不明白基于 Beta.Id 是什么意思。如果 alpha 只能保存具有相同 Beta.Id 的记录,您可能必须在应用程序逻辑中控制它。这需要通过映射来实施额外的复杂构造。

【讨论】:

Beta 中的 Id 属性本质上是一个组 id。一个 Alpha 对象可能有一组特定的 Beta 对象。我试图避免使用查找表,因为我在 242 个组中有 700,000 多个 Alpha 对象和 120,000 多个 Beta 对象。 您不会避免查找表,因为您的关系需要它。 我尝试了几种不同的方法,但都没有奏效。我最终将 Beta 查找移至存储库并添加了 modelBuilder.Entity&lt;Alpha&gt;().Ignore(a =&gt; a.Beta);。这会阻止 EF 添加额外的列或查找表。唯一的缺点是现在必须手动填写 Beta 集合。

以上是关于实体框架代码优先导航问题的主要内容,如果未能解决你的问题,请参考以下文章

如何使用代码优先实体框架在 ASP.Net MVC3 中重新加载多对多导航属性

一对一或零对一实体框架代码优先 Fluent Api

实体框架、代码优先和全文搜索

实体框架4.1代码优先映射问题

实体框架核心关系问题(代码优先) - 重复列

实体框架代码优先:启用迁移错误