【问题标题】:EF Foreign Key using Fluent API使用 Fluent API 的 EF 外键
【发布时间】:2014-01-20 08:36:57
【问题描述】:

这是我的模型。我有车辆和驾驶员的一对一映射。我将首先创建车辆,然后将驾驶员映射到车辆。

public class Driver
{
    public int Id { get; set; }
    public String Name { get; set; }
    public int VehicleId { get; set; }
    public virtual Vehicle Vehicle  { get; set; }
}

public class Vehicle
{  
    public int Id { get; set; }
    public String Name { get; set; }

    public virtual Driver Driver { get; set; }

    public int VehicleGroupId { get; set; }
    public virtual VehicleGroup Vehicles { get; set; }
}

我想在 Driver 类中使用 VehicleId 属性来保存驾驶员正在驾驶的车辆的 ID。

我编写了以下 Fluent API 代码:

modelBuilder.Entity<Vehicle>()
            .HasRequired(d => d.Driver)
            .WithRequiredPrincipal();

但它会在 Drivers 表中创建一个新列 - Vehicle_VehicleId 并将其映射到 Vehicle 表中的 VehicleId。我想映射 Driver 表的 VehicleId。

另外,我是 EF 和 Fluent API 的新手。我发现在 WithRequiredDependent 和 WithRequiredPrincipal 之间进行选择非常令人困惑。如果你能用简单的话来描述它会很高兴。谢谢。

【问题讨论】:

  • 您可以将依赖项和委托人视为实体框架问您:“如果要插入这些表的记录,我应该先在哪里插入记录,表 A 还是表 B?”如果选择表 A 作为主体,表 B 将包含表 A 的外键。顺便提一下,Fluent API 有很好的 c# 文档,请仔细阅读“WithRequiredDependent”和“WithRequiredPrincipal”的说明。

标签: c# entity-framework


【解决方案1】:

这一行:

公共 int VehicleId { 获取;放; }

告诉 EF,through code-conventions,你想要一个指向 VehicleDriver 中的外键。

下面是告诉 EF 你想要一个从 DriverVehicle 的 1:1 关系:

公共虚拟车辆 Vehicle { get;放; }

您应该删除两者并坚持使用您的 Fluent API 配置。

关于WithRequiredPrincipalWithRequiredDependent

您指定VehicleDriver 之间的强制关系,导航从VehicleDriver,因此:Vehicle 1 --> 1 Driver

(Vehicle 是主体,Driver 是从属,因为导航属性位于 Vehicle 并指向 Driver。)

modelBuilder.Entity<Vehicle>()
            .HasRequired(d => d.Driver)
            .WithRequiredDependent();

您指定VehicleDriver 之间的强制关系,导航从DriverVehicle,因此:Vehicle 1 Driver

Vehicle 是依赖项,Driver 是主体,因为导航属性位于指向 VehicleDriver。)

这两个是类似的:

modelBuilder.Entity<Vehicle>()
            .HasRequired(v => v.Driver)
            .WithRequiredPrincipal();

modelBuilder.Entity<Driver>()
            .HasRequired(d => d.Vehicle)
            .WithRequiredDependent();

【讨论】:

  • @jnovo “您应该删除两者并坚持使用 Fluent API 配置。”如果你这样做,那么你如何使用“HasRequired(v => v.Vehicle)”而不引用车辆?
  • @RobWashington 在他的 Fluent API 配置中使用了 Vehicle 的 Driver 属性,而不是相反;您所指的答案中的最后一行代码只是为了完成而进行的替代类似配置的示例
【解决方案2】:

EF 创建Vehicle_VehicleId 列,因为您的Driver 实体上有VehicleIdVehicle

从您的 Driver 实体中删除 VehicleIdVehicle

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

public class Vehicle
{  
    public int Id { get; set; }
    public String Name { get; set; }
}

使用:

modelBuilder.Entity<Vehicle>()
        .HasRequired(d => d.Driver)
        .WithRequiredPrincipal();

您正在设置关系,因此无需在实体类中包含手动属性。

您从导航属性Vehicle 获得VehicleId

IQueryable<int> vehicleIds = context.Drivers.Select(x => x.Id == 123).Vehicles.Id;

【讨论】:

  • 我已将其删除,但仍会创建 Vehicle_VehicleId。不是驱动程序表中的 VehicleId。
  • 这是因为你使用fluent api来定义关系。我已经更新了我的答案。也删除虚拟属性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
  • 2014-12-31
相关资源
最近更新 更多