问题
I am trying to define a composite PK for a class where one of the columns is a FK to another table. The code compiles without any errors but when I try to migrate the changes I get the following error
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 }'.
However, the that is supposedly causing the exception does seem to be in the syntax that is requested.
Given the following classes
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
And the following Fluent API code
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
The equivalent SQL code would be
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
Thank you for any help you can provide.
Edit:
After more research (i.e. experimenting) the problem seems to stem from the use of the navigation property in the PK definition. So changing the code to look like
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
clears the Exception but, of course, I now lost my ParentClass navigation property in ChildClass.
Still perplexed.
回答1:
You can keep the navigation property in your class...
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
...and then use HasForeignKey
instead of MapKey
in your mapping:
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)
If the foreign key has another name in the database table add a column name mapping:
modelBuilder.Entity(Of Models.ChildClass). _
Property(Function(x) x.ParentClassId). _
HasColumnName("ContractId")
回答2:
It seems that you have to have the scalar property in the child class. Keys can only be defined using explicit scalar properties.
来源:https://stackoverflow.com/questions/12765542/cannot-define-composite-pk-with-fluent-api-in-vb-net