我遇到了 EF6 的问题,尽管我相当确定这适用于支持此类映射的先前版本。我担心我知道手头问题的答案,但我希望我做错了什么,或者有比我在这里提出的更好的解决方法。为了清楚起见,所有类都被删除了。
所以我有
public abstract class SoftwareFirmware
{
public long Id { get; private set; }
public ICollection<DeviceType> DeviceTypes { get; private set; }
public SoftwareFirmware()
{
DeviceTypes=new HashSet<DeviceType>();
}
}
和
public class DeviceType
{
public long Id { get; set; }
public virtual ICollection<Firmware> AvailableFirmwareVerions { get; private set; }
public virtual ICollection<Software> AvailableSoftwareVerions { get; private set; }
public DeviceType()
{
AvailableFirmwareVerions = new HashSet<Firmware>();
AvailableSoftwareVerions = new HashSet<Software>();
}
}
如您所见,它定义了多对多关系。我已经定义了两个派生自SoftwareFirmware
的类,恰当地命名为
public class Firmware : SoftwareFirmware {}
和
public class Software : SoftwareFirmware {}
我正在使用 Table Per Hierarchy 继承,因此Software
和Firmware
与鉴别器列存储在同一个表中。最后,我已经映射了 derivedDbContext
的OnModelCreating
方法中的关系
modelBuilder.Entity<DeviceType>().HasMany(d => d.AvailableFirmwareVerions).WithMany(firmware=>firmware.DeviceTypes);
modelBuilder.Entity<DeviceType>().HasMany(d => d.AvailableSoftwareVerions).WithMany(sofware=>sofware.DeviceTypes);
手头的问题是实体框架似乎不支持此映射的继承,因为当 EF 尝试生成数据库时我收到以下信息:
DeviceTypes:FromRole:NavigationProperty 'DeviceTypes' 无效。AssociationType 'DeviceType_AvailableSoftwareVerions' 中 FromRole 'DeviceType_AvailableSoftwareVerions_Target' 的类型 'Software' 必须与声明此 NavigationProperty 的类型 'SoftwareFirmware' 完全匹配。
从这里我收集到一个继承自的类型SoftwareFirmware
对于 NavigationProperty 来说不够好,它必须是一个SoftwareFirmware
类型。如果我将DeviceType
集合从SoftwareFirmware
基类中取出并在每个派生类中复制它,那么一切正常,但这肯定不太理想。
最后,我的问题是 - 是否有另一种方法来配置它,以便我可以将导航属性保留在我的基类中?如果没有,是否有比我描述的更清洁的解决方法?
更新:所以似乎 SQL Server Management Studio 做错了,因为我之前绘制了数据库图表,而没有使用表达式的 WithMany 的重载版本,并且它不包括联结表。即使数据库已被删除并重新创建,SSMS 似乎在添加新图表方面也不能很好地处理模式更改 - 它必须重新启动。严重的痛苦,但我离题了......
作为最后的努力,我恢复到WithMany
映射的无参数版本,通过重新启动应用程序删除并重新创建数据库,重新启动 SSMS,然后看!连接表已创建。我需要做的就是Ignore
为基SoftwareFirmware
类的DeviceTypes
属性添加一个,并干净地生成所有内容。所以我的 FluentAPI 映射代码如下所示:
modelBuilder.Entity<DeviceType>().HasMany(d => d.AvailableFirmwareVerions).WithMany();
modelBuilder.Entity<DeviceType>().HasMany(d => d.AvailableSoftwareVerions).WithMany();
modelBuilder.Entity<SoftwareFirmware>().Ignore(s => s.DeviceTypes);
它生成了这个模式 - 几乎正是我想要的模式(忽略额外的属性):
但是,由于无参数调用WithMany
仅在一侧连接了导航属性,因此更新Software.DeviceTypes
并且Firmware.DeviceTypes
不被 EF 跟踪,所以我回到了我开始的地方。