EntityFramework尝试获取不存在的列 [英] EntityFramework is trying to fetch non-existing column

查看:84
本文介绍了EntityFramework尝试获取不存在的列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



在我的情况下,我有两个表与单对多的关系:

  T_Blog 
- Id
- FeaturedPost

T_Post
- Id
- BlogId

我定义了实体数据模型

  public class T_Blog 
{
[Key]
public int Id {get; set;}
public诠释?特征PostId {get; set;}

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

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

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

这个元数据被定义为EF正在尝试获取 T_Blog_Id 列每次我试图执行db.T_Post.Where(...)ToList();



我知道,只要我的T_Blog有两个引用T_Post,然后EF尝试获取两个Ids。



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

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

解决方案

您应该使用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>博客{get;组; }
public virtual DbSet< T_Post>帖子{get;组; }
}

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

public virtual ICollection< T_Post>帖子{get;组; }

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

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

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

和自动生成迁移

  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);
}
}


EntityFramework is trying to fetch non-existing column and foreign key attribute doesn't help.

In my case, I have two tables with single to multiple relationships:

  T_Blog
- Id
- FeaturedPost

  T_Post
- Id
- BlogId

and I defined entity data model

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;}
}

And having this metadata defined EF is trying to fetch T_Blog_Id column everytime I'm trying to execute db.T_Post.Where(...).ToList();

I got it that as long as my T_Blog has two references to T_Post, then EF is trying to fetch both Ids.

ps: yeah, I know this type of data model is not optimal but this type of denormalization is needed in my case (at least as of now).

How to properly define the second relationship so EF knows what to fetch?

解决方案

You should use the FluentAPI instead of annotations to avoid that kind of mapping fails.

Here is a sample for your model

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; }
}

and the autogenerated migration

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");
    }
}

这篇关于EntityFramework尝试获取不存在的列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆