EF添加Client地址时触发Supplier关联错误的问题求助
问题描述
之前见过类似问题的帖子,已经尝试了所有被采纳的解决方案,但还是报错。我有多个类(Client、Supplier等),每个类都包含List(Of Address),可拥有多个地址。这些类互不继承,但都实现了IAddresses接口,该接口定义了ID、ClassType和List(Of Address)属性(我的代码是VB,也能理解C#解决方案)。
报错信息
尝试给Client添加新地址时,出现如下错误:
Entities in 'DataContext.Addresses' participate in the 'Supplier_Addresses' relationship. 0 related 'Supplier_Addresses_Source' were found. 1 'Supplier_Addresses_Source' is expected.
相关代码
Supplier配置类
Public Class SupplierConfiguration Inherits EntityTypeConfiguration(Of Supplier) Public Sub New() [Property](Function(x) x.Email).HasMaxLength(200) [Property](Function(x) x.GivenName).HasMaxLength(50).IsRequired() [Property](Function(x) x.PhoneH).HasMaxLength(20) [Property](Function(x) x.PhoneM).HasMaxLength(20) [Property](Function(x) x.Status).IsRequired() [Property](Function(x) x.Surname).HasMaxLength(50).IsRequired() [Property](Function(x) x.Title).HasMaxLength(5) HasMany(Function(x) x.Comments).WithRequired(Function(x) x.Parent) HasMany(Function(x) x.Addresses).WithRequired(Function(x) x.Parent) Ignore(Function(x) x.ParentType) End Sub End Class
Client配置类
Public Class ClientConfiguration Inherits EntityTypeConfiguration(Of Client) Public Sub New() [Property](Function(x) x.Alert).IsMaxLength() [Property](Function(x) x.Email).HasMaxLength(200) [Property](Function(x) x.EntityName).HasMaxLength(100).IsRequired() [Property](Function(x) x.Status).IsRequired() HasMany(Function(x) x.Addresses).WithRequired(Function(x) x.Parent) HasMany(Function(x) x.Comments).WithRequired(Function(x) x.Parent) HasMany(Function(x) x.Invoices).WithOptional(Function(x) x.Client) HasMany(Function(x) x.Jobs).WithRequired(Function(x) x.Client) Ignore(Function(x) x.ParentType) End Sub End Class
UnitOfWork类
Imports System.Data.Entity Public Class UnitOfWork Implements IUnitOfWork Private ReadOnly Property _context As DataContext Private _Addresses As AddressRepository Private _Clients As ClientRepository Private _Comments As CommentRepository Private _Suppliers As SupplierRepository Public ReadOnly Property Addresses As IAddressRepository Implements IUnitOfWork.Addresses Get Return _Addresses End Get End Property Public ReadOnly Property Clients As IClientRepository Implements IUnitOfWork.Clients Get Return _Clients End Get End Property Public ReadOnly Property Comments As ICommentRepository Implements IUnitOfWork.Comments Get Return _Comments End Get End Property Public ReadOnly Property Suppliers As ISupplierRepository Implements IUnitOfWork.Suppliers Get Return _Suppliers End Get End Property Public Sub New(context As DataContext) _context = context _Addresses = New AddressRepository(_context) _Clients = New ClientRepository(_context) _Comments = New CommentRepository(_context) _Suppliers = New SupplierRepository(_context) End Sub Public Function Context() As DbContext Return _context End Function Public Function Complete() As Integer Implements IUnitOfWork.Complete Dim log As String = vbNullString Dim errors = _context.GetValidationErrors If errors.Count > 0 Then Stop Dim ReturnValue As Integer Try ReturnValue = _context.SaveChanges Catch ex As System.Data.Entity.Validation.DbEntityValidationException ShowException(ex) ReturnValue = 0 Catch ex2 As Exception ShowException(ex2) ReturnValue = 0 End Try Return ReturnValue End Function Public Sub Dispose() Implements IDisposable.Dispose _context.Dispose() End Sub End Class
Supplier类
Public Class Supplier Implements IAddresses, IComments Property ID As Integer Implements IAddresses.ID, IComments.ID Property Email As String Property EntityName As String Property GivenName As String Property PhoneH As String Property PhoneM As String Property Status As eSupplierStatus Property Surname As String Property Title As String Property Addresses As Addresses Implements IAddresses.Addresses Property Comments As Comments Implements IComments.Comments ReadOnly Property ParentType As String Implements IComments.ParentType, IAddresses.ParentType Get Return Me.GetType.Name End Get End Property End Class
核心疑问
无法理解为何给Client类保存地址时,EF却要求关联Supplier类,二者本应完全独立?
解决方案分析
问题出在EF对关联关系的自动识别混淆上:
- Address类的Parent属性未区分关联对象:当前
Address类的Parent导航属性没有明确指向具体的实体类型,EF会默认把所有实体的Address关联映射到同一个外键关系,导致识别错误。 - 配置未指定专属外键:在
HasMany.WithRequired的配置中,没有明确指定每个实体对应的外键字段,EF自动生成的外键无法区分Client和Supplier的关联关系。
修复步骤
1. 修改Address类,添加区分外键和导航属性
给Address类添加专属外键和导航属性,明确关联对象:
Public Class Address Property ID As Integer ' 其他地址属性... Property ClientId As Integer? Property SupplierId As Integer? Property Client As Client Property Supplier As Supplier End Class
2. 修正Client和Supplier的配置类
明确指定外键和对应导航属性,避免EF混淆:
- ClientConfiguration修改:
' 若地址必须属于Client,将WithOptional改为WithRequired,并设置ClientId非空 HasMany(Function(x) x.Addresses).WithOptional(Function(x) x.Client).HasForeignKey(Function(x) x.ClientId)
- SupplierConfiguration修改:
' 若地址必须属于Supplier,将WithOptional改为WithRequired,并设置SupplierId非空 HasMany(Function(x) x.Addresses).WithOptional(Function(x) x.Supplier).HasForeignKey(Function(x) x.SupplierId)
3. 调整实体类的Addresses属性
确保Client和Supplier的Addresses集合对应正确的关联:
' Client类 Property Addresses As List(Of Address) ' Supplier类 Property Addresses As List(Of Address)
4. 更新数据库结构
修改配置后,生成新的EF迁移脚本并执行,确保数据库中创建正确的外键列。
内容的提问来源于stack exchange,提问作者mdicoope
相关产品推荐
相关产品推荐

