【问题标题】:EF4 (CPT5) ForeignKeyAttribute in base class - Assert Failure entityType != null基类中的 EF4 (CPT5) ForeignKeyAttribute - 断言失败 entityType != null
【发布时间】:2011-01-16 15:34:09
【问题描述】:

尝试在基类中设置 ForeignKeyAttribute 时出错

class User { }

abstract class FruitBase
{    
   [ForeignKey("CreateById")]
   public User CreateBy{ get; set; }

   public int CreateById{ get; set; }     
}

class Banana : FruitBase { }

class DataContext : DbContext
{    
   public DbSet<Banana> Bananas { get; set; }
}

如果我将 FruitBase 代码移动到香蕉中,一切都很好,但我不想这样做,因为会有很多水果,如果可以的话,我想保持相对干燥

这是一个将在 3 月之前解决的已知问题吗? 有谁知道解决方法吗?

【问题讨论】:

  • 附注错误是一个很大的断言失败对话框,如果有人想看,我可以上传图片

标签: c# entity-framework-4 ef-code-first


【解决方案1】:

由于在 DbContext 中放置 DbSet&lt;Banana&gt; 而不是 DbSet&lt;FruitBase&gt; 而导致的问题。以下对象模型按预期工作:

public class User 
{
    public int UserId { get; set; }
}

public abstract class FruitBase
{
    public int Id { get; set; }
    public int CreateById { get; set; }

    [ForeignKey("CreateById")]
    public User CreateBy { get; set; }
}

public class Banana : FruitBase { }

public class DataContext : DbContext
{        
    public DbSet<FruitBase> Fruits { get; set; }                
}

您必须知道,这样做实际上是在创建Polymorphic Association,并且从 CTP5 开始,并非所有继承映射策略都允许多态关联。在这里它工作正常,因为您使用了Table per Hierarchy (TPH)

更新:使用Table per Type (TPT) 策略:

多态关联也适用于 TPT:

public class StackoverflowTestContext : DbContext
{
    public DbSet<FruitBase> Fruits { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Banana>().ToTable("Bananas");
    }         
}

【讨论】:

  • 哦,如果我添加了 Apple,我会将它保留在水果表中吗?我想要的是一张香蕉桌和一张苹果桌以及任何其他类型的桌子……这可能吗?
  • 是的,当然,那么您实际上是在寻找每个类型的表 (TPT) 策略。我已经更新了我的答案,向您展示如何。我还鼓励您阅读我关于 Code First 的继承策略的文章:weblogs.asp.net/manavi/archive/2010/12/24/…
  • 对不起 Morteza,这不是我想要的,它仍然创建一个 Fruits 表,我希望每个水果映射到一个表,FruitBase 只提供这些表的通用结构。我在这里并不追求像多态关联这样复杂的东西。也许我选择 Fruit 作为一个例子已经把它扔进了等式,但它不是故意的。基类用于提供一组通用属性,用于许多概念上不相关的对象
  • 好吧,我要的是 TPC,如果我在 dataContext 中添加一个苹果类和一个 DbSet 来匹配,则从表中删除 [ForeignKey("CreateById")]结构是我想要的,只是没有 FK 映射和 FK 列上的 [Type+Index] 名称。当我把它弹回来时,我得到了断言对话框。
  • 好的,您可能需要特别阅读 TPC 文章中标题为 多态关联与 TPC 存在问题 下的部分。另请阅读我对该文章的 cmets 上“Dimitris Foukas”的回答。简而言之,EF 通常(不仅是 Code First)无法处理您与 TPC 的多态关联。您必须考虑使用 TPT 或放弃您的多态关联(即将其移至子类)。
【解决方案2】:

如上所述,这是 TPC (Table per Concrete Type),这里的答案/解决方法是将 ForeignKeyAttribute 从基础中取出

class User{}

abstract class AuditObjectBase{ // was FruitBase

   // [ForeignKey("CreateById")]
   public abstract User CreateBy{ get; set; } // made abstract

   public int CreateById{ get; set; } // both get and set required public

}

class ItemOne : AuditObjectBase{ // Was Banana

   // added
   [ForeignKey("CreateById")]
   public override User CreateBy{ get; set; }
}

class ItemTwo : AuditObjectBase{ // Added

   [ForeignKey("CreateById")]
   public override User CreateBy{ get; set; }
}

class DataContext : DbContext{

   DbSet<ItemOne> ItemOnes{ get; set; }
   DbSet<ItemTwo> ItemTwos{ get; set; }
}

不是完全 DRY,但至少当你创建一个使用 AuditObjectBase 的对象时,它会强制你实现外键属性,一些不错的 cmets 会提醒你该属性,然后你就走了

基本上是接缝,属性应该添加到在 DbContext 中声明为实体的类中,在这种情况下具有 DbSet 属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多