【问题标题】:Optional 1:1 relationship in Entity Framework Code FirstEntity Framework Code First 中的可选 1:1 关系
【发布时间】:2015-04-30 15:10:11
【问题描述】:

我正在尝试在实体框架中创建我认为可以称为可选 1:1 或可能 0..1:0..1 的关系。我希望能够在两个对象上都有导航属性。

我在现有数据库架构上使用 Entity Framework 的 Fluent API。

为简单起见,我们假设以下表格:

Car
    Id int not null

Driver
    Id int not null
    CarId int null unique

使用以下类:

public class Car
{
    public int Id { get; set; }
    public virtual Driver { get; set; }
}

public class Driver
{
    public int Id { get; set; }
    public virtual Car { get; set; }
}

这个想法是 Car 和 Driver 可以相互独立存在,但是当 Driver 与 Car 关联时,它是一种互斥关联:Driver 只能与该 Car 关联,而该 Car 只能关联给那个司机。

我尝试了以下流畅的配置:

内部驱动配置:

HasOptional(d => d.Car)
    .WithOptionalDependent()
    .Map(d => d.MapKey("CarId"));

在汽车内部配置

HasOptional(c => cDriver)
    .WithOptionalPrincipal()
    .Map(d => d.MapKey("CarId"));

当我尝试这个时,我得到以下信息:

指定的架构无效。错误: (203,6):错误 0019:类型中的每个属性名称必须是唯一的。已定义属性名称“CarId”。

有没有办法在 Entity Framework 中使用两个对象的导航属性对此场景进行建模?

【问题讨论】:

  • 为什么两者都有d.MapKey("CarId")?一个不是CarId,另一个是DriverId
  • Car 表没有 DriverId 列。如果 Car 表中有 DriverId 列,它将允许指向与指向它的驱动程序不同的驱动程序的汽车 - 它是 1:1 或 0:0

标签: c# .net entity-framework


【解决方案1】:

您不需要在两个流利的类中都设置它。我很惊讶这是您收到的错误,而不是关系已经建立。

您的 Drive 课程需要 CarId 作为课程的一部分:

public class Driver 
{
    public int Id { get; set; }
    // Make this int? if a Driver can exist without a Car
    public int CarId { get; set; }
    public virtual Car { get; set; }
}

那么你只需要在 Driver 的 Fluent Config 文件中使用这个,而在 Car 中什么都不需要。

HasOptional(d => d.Car)
    .WithOptionalDependent()
    .Map(d => d.MapKey("CarId"));

【讨论】:

  • 我试过了,它抱怨属性 JobId 被双重定义Schema specified is not valid. Errors: (204,6) : error 0019: Each property name in a type must be unique. Property name 'CarId' was already defined.。如果我删除 CarId 属性,我会得到Invalid column name 'Driver_ID' 的问题,这导致我认为我需要在两端进行流畅的配置
  • 根据我上面的内容,您的 Car C# 对象与上面的相同吗?你在 Car 的 fluent setup 中没有依赖设置?
【解决方案2】:

您可以在没有 Fluent API 的情况下做到这一点:

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

    public string Name { get; set; }

    public int? DriverId { get; set; }

    [ForeignKey("DriverId")]
    public virtual Driver Driver { get; set; }
}

public class Driver
{
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual ICollection<Car> Cars { get; set; }
}

然后你需要检查司机是否已经有车,以保证他只能有一辆。

【讨论】:

  • 这是我开始的地方,当我没有 Car.Driver 时它工作正常,一旦我添加带有上述注释的 Car.Driver 就会导致错误Unable to determine the principal end of an association between the types 'Driver' and 'Car'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
  • 所有汽车都必须有司机?所有司机都必须有车吗?
  • 不,这种关系是可选的但排他性的 - 我认为 EF 很难认为它应该是 1:1 或其他东西,而不是 0:0 或 1:1
  • 如果是独占,那车的主键一定是司机的主键……但那样的话,车就不能没有司机的存在……对吗?
  • 但是任何汽车都可以与任何驱动程序相关联,前提是任何一方都没有关联,并且汽车可以在没有驱动程序的情况下存在,反之亦然,因此它们的主键无法匹配,因为它们都是独立创建的,然后可能会关联。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-28
  • 2011-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多