0

EntityFramework versucht, eine nicht vorhandene Spalte abzurufen, und das Fremdschlüsselattribut hilft nicht.EntityFramework versucht, eine nicht vorhandene Spalte abzurufen

In meinem Fall, ich habe zwei Tabellen mit einzelnen auf mehrere Beziehungen:

T_Blog 
- Id 
- FeaturedPost 

    T_Post 
- Id 
- BlogId 

und I definierten Modellelementdaten

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

Und mit dieser Metadaten definiert EF versucht T_Blog_Id Spalte zu holen jedes Mal, wenn ich versuche, db.T_Post.Where (...) auszuführen. ToList();

Ich habe verstanden, dass, solange mein T_Blog zwei Verweise auf T_Post hat, EF versucht, beide IDs zu holen.

ps: Ja, ich weiß, dass diese Art von Datenmodell nicht optimal ist, aber diese Art von Denormalisierung ist in meinem Fall (zumindest ab sofort) erforderlich.

Wie definiert man die zweite Beziehung richtig, damit EF weiß, was zu holen ist?

Antwort

3

Sie sollten die FluentAPI statt Anmerkungen verwenden, um diese Art zu vermeiden Mapping ausfällt. Hier

ist ein Beispiel für Ihr Modell

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

und die automatisch generierte 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"); 
    } 
} 
+0

Fluent API ist groß, diese Art von Verwirrung zu vermeiden. Ich werde es versuchen. Ab sofort waren Attribute bequemer, solange weniger Code benötigt wurde und (was noch wichtiger ist) weniger umzuformen, wenn etwas geändert wurde. –

1

Ein bisschen nachdem ich eine Stunde in meinen Forschungen verloren habe, fand ich die Antwort. Wenn EF nicht in der Lage ist, die Zuordnung zu definieren, sollten Sie nicht nur die ForeignKey definieren, sondern auch die 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;} 
} 

gefunden here

Verwandte Themen