Entity Framework 6: one-to-one relationship with i

2019-09-02 04:35发布

I'm using EF6 Code First and here's a simple model which reproduces my issue:

abstract class GeoInfo
{
    public int Id { get; set; }
    public double CoordX { get; set; }
    public double CoordY { get; set; }
}

class PersonGeoInfo : GeoInfo
{
    [Required]
    public Person Person { get; set; }
}

class CarGeoInfo : GeoInfo
{
    [Required]
    public Car Car { get; set; }
}

class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual PersonGeoInfo PersonGeoInfo { get; set; }
}

class Car
{
    public int Id { get; set; }
    public string Number { get; set; }
    public virtual CarGeoInfo CarGeoInfo { get; set; }
}

And a context:

class MyContext : DbContext
{
    public DbSet<GeoInfo> GeoInfos { get; set; }
    public DbSet<PersonGeoInfo> PersonGeoInfos { get; set; }
    public DbSet<CarGeoInfo> CarGeoInfos { get; set; }
    public DbSet<Person> Persons { get; set; }
    public DbSet<Car> Cars { get; set; }
}

Entity Framework generates this database:

db schema

Look at GeoInfoes foreign keys constraints. They both are in one column and using this database is imposible. But EF didn't warned me, it just throws database exception: The INSERT statement conflicted with the FOREIGN KEY...

I've tried to use TPT strategy - the same problem, but mixing is between association and inheritance keys.

I've tried to explicitly define foreign keys in model - didn't help. Nothing stops EF from generating a FK constraint in the same PK column.

I can't create a base class for a Car and a Person because in real app they are already participate in another hierarchies.

Am I using Entity Framework wrong or it really can't map one-to-one relationship along with inheritance to a database?

1条回答
疯言疯语
2楼-- · 2019-09-02 05:33

I think you can resolve your problem with this model:

public class GeoInfo
{
    public int Id { get; set; }
    public double CoordX { get; set; }
    public double CoordY { get; set; }

}

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }

    [ForeignKey("PersonGeoInfo")]
    public int? PersonGeoInfoId { get; set; }

    public virtual GeoInfo PersonGeoInfo { get; set; }
}

public class Car
{
    public int Id { get; set; }
    public string Number { get; set; }

    [ForeignKey("CarGeoInfo")]
    public int? CarGeoInfoId { get; set; }

    public virtual GeoInfo CarGeoInfo { get; set; }
}

This way, a Person and a Car are associated with a GeoInfo, and and when you want to find a person by their coordinates, you could do this:

 int geoInfoId = 3;
 var person=_db.Persons.FirstOrDefault(p=>p.PersonGeoInfoId==geoInfoId);

But as you can see, with this model you are going to have one-to many relationships between Person and GeoInfo and Car and GeoInfo. I think this model could be more real because, eg, two people could have the same coordinates.

查看更多
登录 后发表回答