EntityFramework 正在尝试获取不存在的列

EntityFramework is trying to fetch non-existing column

EntityFramework 正在尝试获取不存在的列并且外键属性没有帮助。

在我的例子中,我有两个单对多关系表ps:

  T_Blog
- Id
- FeaturedPost

  T_Post
- Id
- BlogId

并且我定义了实体数据模型

public class T_Blog
{
    [Key]
    public int Id {get;set;}
    public int? FeaturedPostId {get;set;}

    [ForeignKey("FeaturedPostId")]
    public virtual T_Post FeaturedPost {get;set;}
    public virtual ICollection<T_Post> Posts {get;set;}
}

public class T_Post
{
    [Key]
    public int Id {get;set;}
    [Required]
    public int BlogId {get;set;}

    [ForeignKey("BlogId")]
    public T_Blog Blog {get;set;}
}

并且定义了这个元数据,每次我尝试执行 db.T_Post.Where(...).ToList();

时,EF 都会尝试获取 T_Blog_Id

我知道只要我的 T_Blog 有两个对 T_Post 的引用,EF 就会尝试获取这两个 ID。

ps:是的,我知道这种类型的数据模型不是最优的,但在我的情况下需要这种类型的非规范化(至少到目前为止)。

如何正确定义第二个关系以便 EF 知道要获取什么?

在我研究了一个小时之后,我找到了答案。如果 EF 无法定义映射,您不仅应该定义 ForeignKey,还应该定义 InverseProperty

public class T_Blog
{
    [Key]
    public int Id {get;set;}
    public int? FeaturedPostId {get;set;}

    [ForeignKey("FeaturedPostId")]
    public virtual T_Post FeaturedPost {get;set;}
    [InverseProperty("Blog")]
    public virtual ICollection<T_Post> Posts {get;set;}
}

找到here

您应该使用 FluentAPI 而不是注释来避免这种映射失败。

这是您的模型示例

public class BlogContext : DbContext
{
    public BlogContext()
        : base( "name=BlogContext" )
    {
    }

    protected override void OnModelCreating( DbModelBuilder modelBuilder )
    {
        base.OnModelCreating( modelBuilder );

        var blog = modelBuilder.Entity<T_Blog>();

        blog.HasKey( e => e.Id );
        blog.HasOptional( e => e.FeaturedPost )
            .WithMany()
            .HasForeignKey( e => e.FeaturedPostId )
            .WillCascadeOnDelete( false );

        var post = modelBuilder.Entity<T_Post>();

        post.HasKey( e => e.Id );
        post.HasRequired( e => e.Blog )
            .WithMany( e => e.Posts )
            .HasForeignKey( e => e.BlogId )
            .WillCascadeOnDelete( true );
    }

    public virtual DbSet<T_Blog> Blogs { get; set; }
    public virtual DbSet<T_Post> Posts { get; set; }
}

public class T_Blog
{
    public int Id { get; set; }

    public virtual ICollection<T_Post> Posts { get; set; }

    public int? FeaturedPostId { get; set; }
    public virtual T_Post FeaturedPost { get; set; }
}

public class T_Post
{
    public int Id { get; set; }

    public int? BlogId { get; set; }
    public virtual T_Blog Blog { get; set; }
}

和自动生成的迁移

public partial class InitialCreate : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.T_Blog",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    FeaturedPostId = c.Int(),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.T_Post", t => t.FeaturedPostId)
            .Index(t => t.FeaturedPostId);

        CreateTable(
            "dbo.T_Post",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    BlogId = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.T_Blog", t => t.BlogId, cascadeDelete: true)
            .Index(t => t.BlogId);

    }

    public override void Down()
    {
        DropForeignKey("dbo.T_Blog", "FeaturedPostId", "dbo.T_Post");
        DropForeignKey("dbo.T_Post", "BlogId", "dbo.T_Blog");
        DropIndex("dbo.T_Post", new[] { "BlogId" });
        DropIndex("dbo.T_Blog", new[] { "FeaturedPostId" });
        DropTable("dbo.T_Post");
        DropTable("dbo.T_Blog");
    }
}