Entity framework6、非主键列上1到0..1关系的流畅映射

Entity framework 6, fluent mapping of 1 to 0..1 relationship on non-primary-key columns

我正在尝试将 objectcontext/edmx 系统迁移到具有流畅映射的 dbcontext (EF6)。我有几个像下面这样的例子。 Principal table 与 dependent table 有关系,其中 dependent table 中的非 PK 列保存 principal 中 PK 列的值。就其本身而言,这将是一个一对多的关系,但在相关的 table FK 列上有一个唯一索引。使用 EDMX 映射,只要您使用映射而不是引用约束来定义关系,这就可以正常工作。下面是一个 executable 示例 - 您不需要数据库,因为它目前还没有那么远:

Imports System.Data.Entity
Imports System.Data.Entity.ModelConfiguration
Module Module1

  Sub Main()
    Using session As New SaturnEntities
      Dim res = session.BookingLegSet.Select(Function(x) New With {x.Prefix, x.ID, x.AddressDetails.Address}).ToList
    End Using
  End Sub



End Module

Partial Public Class BookingLeg
  Public Property Prefix As String
  Public Property ID As Integer
  Public Property LegIndex As Integer
  Public Overridable Property AddressDetails As BookingLegAddress
End Class

Partial Public Class BookingLegAddress
  Public Property Prefix As String
  Public Property ID As Integer
  Public Property Address As String
  Public Overridable Property BookingLeg As BookingLeg
  Property JobLegPrefix As String
  Property JobLegID As Integer?


End Class

Public Class BookingLegConfig
  Inherits EntityTypeConfiguration(Of BookingLeg)

  Public Sub New()
    ToTable("JobLegs", "dbo")
    HasKey(Function(x) New With {x.Prefix, x.ID})
    HasOptional(Function(x) x.AddressDetails).WithRequired(Function(x) x.BookingLeg).Map(Function(x) x.MapKey("Prefix", "ID"))
  End Sub
End Class

Public Class BookingLegAddressConfig
  Inherits EntityTypeConfiguration(Of BookingLegAddress)

  Public Sub New()
    ToTable("JobAddresses", "dbo")
    HasKey(Function(x) New With {x.Prefix, x.ID})
    HasRequired(Function(x) x.BookingLeg).WithOptional(Function(x) x.AddressDetails).Map(Function(x) x.MapKey("JobLegPrefix", "JobLegID"))
  End Sub
End Class

Partial Public Class SaturnEntities
  Inherits DbContext


  Public Sub New()
    MyBase.New("data source=dbSaturn;initial catalog=Saturn;integrated security=True;MultipleActiveResultSets=True;")
  End Sub

  Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
    modelBuilder.Configurations.Add(New BookingLegConfig)
    modelBuilder.Configurations.Add(New BookingLegAddressConfig)
  End Sub

  Public Overridable Property BookingLegAddressSet() As DbSet(Of BookingLegAddress)
  Public Overridable Property BookingLegSet() As DbSet(Of BookingLeg)
End Class

BookingLeg 是主体实体,BookingLegAddress 是从属实体。依赖项中的 JobLegPrefix 和 JobLegID 要么为 null,要么将保存 BookingLeg 记录中的 Prefix 和 ID 值。当您 运行 这样做时,您会收到一条错误消息,指出 AddressDetails 配置的映射信息存在冲突。我已经尝试了很多不同的方法来映射它,但没有任何进展 - 谁能告诉我我需要做什么?

删除

HasOptional(Function(x) x.AddressDetails).WithRequired(Function(x) x.BookingLeg).Map(Function(x) x.MapKey("Prefix", "ID"))

来自 BookingLegConfig class 的行。每个单独的关系只能在一个地方配置一次(两个相关实体中任何一个的配置的一部分,但不能同时在两个实体中配置)。在这种特殊情况下,您应该将第二个配置保留在 BookingLegAddressConfig class

HasRequired(Function(x) x.BookingLeg).WithOptional(Function(x) x.AddressDetails).Map(Function(x) x.MapKey("JobLegPrefix", "JobLegID"))

因为它指定了正确的 FK 列名称。

此外,EF6 不支持针对此类关系的 explicit FK 列 - 没有 HasForeignKey fluent API,MapKey 适用于指定 shadow 属性(和列)名称。因此,另外从 BookingLegAddress class:

中删除 JobLegPrefixJobLegID 属性
Partial Public Class BookingLegAddress
  Public Property Prefix As String
  Public Property ID As Integer
  Public Property Address As String
  Public Overridable Property BookingLeg As BookingLeg
End Class