Search code examples
sqlitemappingcode-firstentity-framework-core

Map reference property fields to the same table as root class


I have the model with reference properties

internal class AstronomycalBody : IAstronomycalBody
{
    public long Id { get; set; }

    public string Name { get; set; }

    public Coord Coord { get; set; }

    public long Mass { get; set; }

    public double Speed { get; set; }

    public IAstronomycalBody CentralObject { get; set; }
}

public class Coord
{
    public long X { get; set; }

    public long Y { get; set; }

    public long Z { get; set; }
}

I want to use mapping like this

internal class AstronomycalBodyContext : DbContext
{
    public DbSet<AstronomycalBody> AstronomycalBody { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlite(DbSettings.ConnectionString);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<AstronomycalBody>().Property(p => p.Coord.X).ForSqliteHasColumnName("CoordX");
        modelBuilder.Entity<AstronomycalBody>().Property(p => p.Coord.Y).ForSqliteHasColumnName("CoordY");
        modelBuilder.Entity<AstronomycalBody>().Property(p => p.Coord.Z).ForSqliteHasColumnName("CoordZ");
        modelBuilder.Entity<AstronomycalBody>().Property(p => p.CentralObject.Id).ForSqliteHasColumnName("CentralObjectId");
    }
}

to map the model on this table:

AstronomycalBody Table

Currently, the compiler is throwing this exception...

enter image description here


Solution

  • Your AstronomycalBody is not a valid EF entity model class.

    First, EF Core does not support Complex/value types yet, so the Coord member should be expanded in place.

    Second, EF does not work with interfaces, so every navigation reference / collection element type should be entity class.

    With that being said, not sure how your IAstronomycalBody looks like and how you can implement it (you might need explicit implementation of some members), but the entity class should be like this:

    internal class AstronomycalBody //: IAstronomycalBody
    {
        public long Id { get; set; }
        public string Name { get; set; }
        //public Coord Coord { get; set; }
        public long CoordX { get; set; }
        public long CoordY { get; set; }
        public long CoordZ { get; set; }
        public long Mass { get; set; }
        public double Speed { get; set; }
        public AstronomycalBody CentralObject { get; set; }
    }
    

    Now, since by convention it will generate the exact table shown, simply remove all shown lines in OnModelCreating and you are done.