【问题标题】:Entity Framework 6: one-to-one relationship with inheritanceEntity Framework 6:与继承的一对一关系
【发布时间】:2015-01-26 13:12:03
【问题描述】:

我使用的是 EF6 Code First,这是一个重现我的问题的简单模型:

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

还有一个上下文:

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 生成这个数据库:

查看GeoInfoes 外键约束。他们都在一个列中,使用这个数据库是不可能的。但是 EF 并没有警告我,它只是抛出了数据库异常:The INSERT statement conflicted with the FOREIGN KEY...

我尝试使用 TPT 策略 - 同样的问题,但混合是在关联键和继承键之间。

我尝试在模型中明确定义外键 - 没有帮助。没有什么能阻止 EF 在同一 PK 列中生成 FK 约束。

我无法为Car 和Person 创建基类,因为在实际应用中它们已经参与了另一个层次结构。

我是否使用了错误的实体框架,或者它真的无法将一对一的关系与继承一起映射到数据库?

【问题讨论】:

  • 您需要CarGeoInfo 和PersonGeoInfo 做什么? PK, FK 是因为一对一的关系。如果您想拥有单独的键,请从您的models 中删除virtual 属性,这将在GeoInfo 表中生成FK 列。
  • @Ghukas 不,不会
  • 为什么 TPT 策略不适应您的场景?
  • 是的,它会的,我使用了您示例中的类,没有 virtual 属性。 EF 已为 Cars 和 People 实体生成外键。我正在使用 EF 6.1.2
  • @Ghukas 很奇怪,我也刚试过。您能否提供完整的示例代码作为答案?

标签: c# entity-framework inheritance ef-code-first one-to-one


【解决方案1】:

我认为您可以使用此模型解决您的问题:

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

这样,Person 和 Car 与 GeoInfo 相关联,当你想通过坐标找到一个人时,你可以这样做:

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

但正如您所见,使用此模型,您将在 Person 和 GeoInfo 和 Car 和 GeoInfo 之间建立一对多的关系。我认为这个模型可能更真实,因为例如,两个人可以有相同的坐标。

【讨论】:

  • 嗯,在我的情况下,不可能有两个人在一个 GeoInfo,但总的来说,想法是正确的 - 我们可以从一对零开始一对多关系-or-one
猜你喜欢
  • 1970-01-01
  • 2012-01-20
  • 2013-01-26
  • 1970-01-01
  • 2017-02-17
  • 2018-03-08
  • 2011-01-06
  • 1970-01-01
  • 2019-08-07
相关资源
最近更新 更多