多对多关系在其中一个子表上插入空FK记录

时间:2013-10-10 06:50:57

标签: vb.net entity-framework foreign-keys many-to-many code-first

我有一个具有这种结构的模型

1 -TABLEA

2 - 模型

3 -TABLEB

说明: 表格模型与TABLEA具有1对多的关系 表格模型与TABLEB具有1对多的关系 TABLEA与TABLEB具有多对多的关系

这些表中的每一个都有这种类型的模型定义:

    With modelBuilder.Entity(Of TABLEA)()
        .Property(Function(t) t.dbTableAID).
            HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
        .HasKey(Function(t) t.dbTableAID)
        .Property(Function(t) t.Name).
            HasColumnName("TableName")
        .ToTable("TI")

每种类型都定义如下:

Public Class Model

Public Sub New()
    Me.TableAs = New HashSet(Of TableA)()
    Me.TableBs = New HashSet(Of TableB)()
End Sub

Public Property model_id as integer

Public Overridable Property TableAs() As ICollection(Of TableA)
Public Overridable Property TableBs() As ICollection(Of TableB)

Public Sub LoadModel(Query)

      For Each objTableA In Query.cbsSrcCubes
        Dim objDb As TableA = New TableA()
        Me.TableAs.Add(objDbSrcCube.CastCubeToDB(objDb))
    Next

      For Each objTableB In Query.cbsSrcCubes
        Dim objDb As TableB = New TableB()
        Me.TableBs.Add(objDbSrcCube.CastCubeToDB(objDb))
    Next
End Sub

End Class


Public Class TableA

Public Sub New()
    Me.TableBs = New HashSet(Of TableB)()
End Sub

Public Property TableA_id as integer

Public Overridable Property Model() As Model
Public Overridable Property TableBs() As ICollection(Of TableB)

End Class

Public Class TableB

Public Sub New()
    Me.TableAs = New HashSet(Of TableA)()
End Sub

Public Property TableB_id as integer

Public Overridable Property Model() As Model
Public Overridable Property TableAs() As ICollection(Of TableA)

Public Sub LoadTableA(Query)
      For Each objTableA In Query.TableACol
        Dim objDb As TableA = New TableA()
        Me.TableAs.Add(objDb)
    Next
End Sub


End Class

这是上下文的定义

Public Class QDModelContext
Inherits DbContext

Public Property Models() As DbSet(Of Model)
Public Property TableAs() As DbSet(Of TableA)
Public Property TableBs() As DbSet(Of TableB)

Protected Overrides Sub OnModelCreating(ByVal modelBuilder As DbModelBuilder)
    modelBuilder.Conventions.Remove(Of PluralizingTableNameConvention)()

    'Specific Features of the MODEL Objects
    With modelBuilder.Entity(Of Model)()
        .Property(Function(t) t.model_id).
            HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
        .HasKey(Function(t) t.model_id)
        .Property(Function(t) t.Name).
            HasColumnName("ModelName")
    End With

    With modelBuilder.Entity(Of TableA)()
        .Property(Function(t) t.tablea_id).
            HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
        .HasKey(Function(t) t.tablea_id)
        .Property(Function(t) t.Name).
            HasColumnName("TableAName")

        modelBuilder.Entity(Of TableA)().
            HasMany(Function(t) t.TableBs).
            WithMany(Function(t) t.TableAs).
        Map(Sub(m)
                m.ToTable("TableA-TableB")
                m.MapLeftKey("tablea_id")
                m.MapRightKey("tableb-id")
            End Sub)
    End With

    With modelBuilder.Entity(Of TableB)()
        .Property(Function(t) t.tableb_id).
            HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
        .HasKey(Function(t) t.tableb_id)
        .Property(Function(t) t.Name).
            HasColumnName("TableBName")
    End With

End Class

保存从Main调用的例程:

    Public Function PersistModel(CurrentModel As Model)
        Try
            Using context As New QDModelContext()
                Dim ModelObj As Model = New Model()
                context.Models.Add(ModelObj)
                context.SaveChanges()
            End Using
        Catch ex As Exception
            buildError("Couldn't Persist Model.", ex.Source & ": " & Err.Description, ex)
        End Try
    End Function

我已经尝试正确定义FK关系并遇到以下错误:

        modelBuilder.Entity(Of TableB)().
            HasRequired(Function(t) t.Model).
            WithMany(Function(t) t.TableBs).
        Map(Sub(m)
                m.MapKey("ModelID_FK")
            End Sub)

它工作正常......但是一旦我添加了多对多的关系,它就说它无法将TableA中的某些对象映射到模型。

所以如果我将其设置为Optional:

        modelBuilder.Entity(Of TableB)().
            HasOPTIONAL(Function(t) t.Model).
            WithMany(Function(t) t.TableBs).
        Map(Sub(m)
                m.MapKey("ModelID_FK")
            End Sub)

它运行正常,它创建了连接表TableA-TableB,但是它在表B中添加了一些具有ModelID_FK空值的行重复...我认为是表B中不存在的关系TableA-TableB B值的那些。 奇怪的...

我想知道它是否与加载订单或某些实体之间的循环或顺序有关...

任何帮助都会非常感激。感谢!!!

1 个答案:

答案 0 :(得分:0)

我认为这个问题与加载多对多

有关

每个表A和B都有一个标识列作为密钥。 当我加载表A时,我加载了B项的集合。 和表B被加载。

当我将更改保存为HasOptional时,所有表A项都映射到多对多的表A和表B中,表B包含所有表B项和所有B项,它们存在于连接表中但具有NULL外键到模特。

因此,不会发生到多对多的一侧的映射。

所以我认为在A中加载Ta​​bleB项目的时机存在问题。 当我保存更改时,Join表上的表B项目不会被识别为存在,因此不会与现有项目映射...这就是EF在表B中创建这些新条目以将其映射到某些内容的原因。

如果我将外键从Model更改为Table B到HasRequired,我会收到以下错误:

Entities in 'Context.TableB' participate in the 'TableB_Model' relationship. 0 related 'TableB_Model_Target' were found. 1 'TableB_Model_Target' is expected."}

我越来越近,但还没到。 任何帮助将不胜感激!