无法在VB.NET中使用Fluent API定义复合PK

时间:2012-10-07 02:07:40

标签: vb.net entity-framework fluent-interface

我正在尝试为一个类定义一个复合PK,其中一列是另一个表的FK。代码编译时没有任何错误,但是当我尝试迁移更改时,我收到以下错误

PM> Update-Database -Force -TargetMigration:0
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
System.InvalidOperationException: The properties expression 'x => new VB$AnonymousType_0`2(RtepNumber = x.RtepNumber, ContractId = x.Contract.ContractId)' is not valid. The expression should represent a property: C#: 't => t.MyProperty'  VB.Net: 'Function(t) t.MyProperty'. When specifying multiple properties use an anonymous type: C#: 't => new { t.MyProperty1, t.MyProperty2 }'  VB.Net: 'Function(t) New With { t.MyProperty1, t.MyProperty2 }'.

The properties expression 'x => new VB$AnonymousType_0`2(RtepNumber = x.RtepNumber, ContractId = x.Contract.ContractId)' is not valid. The expression should represent a property: C#: 't => t.MyProperty'  VB.Net: 'Function(t) t.MyProperty'. When specifying multiple properties use an anonymous type: C#: 't => new { t.MyProperty1, t.MyProperty2 }'  VB.Net: 'Function(t) New With { t.MyProperty1, t.MyProperty2 }'.

然而,据说导致异常的那个似乎确实是在请求的语法中。

鉴于以下课程

Public Class ParentClass
   Public Property ParentClassId as String

   Public Property Title As String

   Public Property ChildClasses As ICollection(Of ChildClass)
End Class

Public Class ChildClass      
   Public Property ParentClass As ParentClass

   Public Property ChildClassId As String

   Public Property Title As String
End Class

以下Fluent API代码

Protected Overrides Sub OnModelCreating(ByVal modelBuilder As System.Data.Entity.DbModelBuilder)
   MyBase.OnModelCreating(modelBuilder)

   modelBuilder.Entity(Of Models.ChildClass).HasRequired(Function(x) x.ParentClass).WithMany(Function(x) x.ChildClasses).Map(Function(x) x.MapKey("ContractId"))

   modelBuilder.Entity(Of Models.ChildClass).HasKey(Function(x) New With {x.ParentClass.ParentClassId, x.ChildClassId})
End Sub

等效的SQL代码是

CREATE TABLE [dbo].[ParentClass](
    [ParentClassId] [nvarchar](10) NOT NULL,
    [Title] [nvarchar](25) NOT NULL,
 CONSTRAINT [PK_ParentClass] PRIMARY KEY CLUSTERED 
(
    [ParentClassId] ASC
)
)
GO

CREATE TABLE [dbo].[ChildClass](
    [ParentClassId] [nvarchar](10) NOT NULL,
    [ChildClassId] [nvarchar](10) NOT NULL,
    [Title] [nvarchar](25) NOT NULL,
 CONSTRAINT [PK_ChildClass] PRIMARY KEY CLUSTERED 
(
    [ParentClassId] ASC,
    [ChildClassId] ASC
)
)
GO

ALTER TABLE [dbo].[ChildClass]  WITH CHECK ADD  CONSTRAINT [FK_ChildClass_ParentClass] FOREIGN     KEY([ParentClassId])
REFERENCES [dbo].[ParentClass] ([ParentClassId])
GO

ALTER TABLE [dbo].[ChildClass] CHECK CONSTRAINT [FK_ChildClass_ParentClass]
GO

感谢您提供任何帮助。

修改

经过更多研究(即试验)后,问题似乎源于PK定义中导航属性的使用。所以改变代码看起来像

Public Class ChildClass      
   Public Property ParentClassId As String

   Public Property ChildClassId As String

   Public Property Title As String
End Class

Protected Overrides Sub OnModelCreating(ByVal modelBuilder As System.Data.Entity.DbModelBuilder)
   MyBase.OnModelCreating(modelBuilder)

   modelBuilder.Entity(Of Models.ChildClass).HasKey(Function(x) New With {x.ParentClassId, x.ChildClassId})
End Sub

清除Exception,但当然,我现在在ChildClass中丢失了ParentClass导航属性。

仍然感到困惑。

2 个答案:

答案 0 :(得分:0)

您可以在班级中保留导航属性...

Public Class ChildClass      
    Public Property ParentClassId As String

    Public Property ChildClassId As String

    Public Property Title As String

    Public Property ParentClass As ParentClass
End Class

...然后在映射中使用HasForeignKey代替MapKey

modelBuilder.Entity(Of Models.ChildClass). _
    HasKey(Function(x) New With {x.ParentClassId, x.ChildClassId})

modelBuilder.Entity(Of Models.ChildClass). _
    HasRequired(Function(x) x.ParentClass). _
    WithMany(Function(x) x.ChildClasses). _
    HasForeignKey(Function(x) x.ParentClassId)

如果外键在数据库表中有另一个名称,则添加一个列名映射:

modelBuilder.Entity(Of Models.ChildClass). _
    Property(Function(x) x.ParentClassId). _
    HasColumnName("ContractId")

答案 1 :(得分:0)

您似乎拥有在子类中具有标量属性。只能使用显式标量属性来定义键。