Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Table Splitting: not in the same type hierarchy / do not have a valid one to one foreign key relationship

I'm using Entity Framework 6 with a Code-First approach, and I want two entities to be put in the same table. What am I doing wrong?

[Table("Review")]
public class Review
{
    public int Id { get; set; }
    public PictureInfo PictureInfo { get; set; }
    public int PictureInfoId { get; set; }
}

[Table("Review")]
public class PictureInfo
{
    [Key, ForeignKey("Review")]
    public int ReviewId { get; set; }
    public Review Review { get; set; }
}

The error I get: The entity types 'PictureInfo' and 'Review' cannot share table 'Review' because they are not in the same type hierarchy or do not have a valid one to one foreign key relationship with matching primary keys between them.

What am I doing wrong?

like image 346
Andrew Avatar asked Jun 27 '14 14:06

Andrew


2 Answers

Seems like the problem was that the relationship was interpreted as one-to-0..1 instead of one-to-one.

The foreign key int PictureInfoId on the Review end was unneeded/ignored, so its non-nullability did not make the Review end of the relationship required. Removing this unneeded key and adding the [Required] attribute to the PictureInfo navigational property solved it.

Here's the corrected Review class.

[Table("Review")]
public class Review
{
    public int Id { get; set; }
    [Required]
    public PictureInfo PictureInfo { get; set; }
}
like image 132
Andrew Avatar answered Oct 15 '22 21:10

Andrew


I've managed to achieve what you wanted with fluent api. Fluent api offers much richer options for configuration than data-annotations. I've changed a bit your entity classes:

public class Review
{
    public int Id { get; set; }
    public PictureInfo PictureInfo { get; set; }
}

PictureInfoId property is not necessary as foreign key relationship will be done on primary keys of both entities.

public class PictureInfo
{
    public int Id { get; set; }
    public Review Review { get; set; }
}

Because Review and PictureInfo will be mapped to the same table they need to share the same primary key column so for PictureInfo and Review this column should have the same name. If you would like to keep in PictureInfo primary key property named ReviewId you can do this but you would need then to map its name to "Id". Finaly the DbContext:

public class MyDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Review>().HasKey( e => e.Id );
        modelBuilder.Entity<Review>()
            .HasRequired(e => e.PictureInfo)
            .WithRequiredDependent(e => e.Review);
        modelBuilder.Entity<Review>().Map(m => m.ToTable("Review"));
        modelBuilder.Entity<PictureInfo>().Map(m => m.ToTable("Review"));
        modelBuilder.Entity<PictureInfo>().HasKey(e => e.Id);

        base.OnModelCreating(modelBuilder);
    }

    public DbSet<Review> Reviews { get; set; }
    public DbSet<PictureInfo> PictureInfos { get; set; }
}

OnModelCreating holds fluent api mapping definition. All you have to do is to define primary keys on both entities with the same name, bind those 2 entities with 1-1 relation and then map them to the same table.

like image 7
mr100 Avatar answered Oct 15 '22 21:10

mr100