同一个表中的两个一对多关系

我有一个名为SystemAccount的表,它(直到最近)有一个MasterAccountID ,它指向其父帐户(显然是一个int? )。 我的客户现在告诉我,有时某个帐户可能有2个父帐户(没有比这更多)。 我一直在尝试在我的SystemAccount类中进行调整,但它没有产生我想要的关系。

这是类代码的一部分:

 [ForeignKey("MasterAccount")] public int? MasterAccountID { get; set; } [ForeignKey("SecondMasterAccount")] public int? SecondMasterAccountID { get; set; } public virtual SystemAccount MasterAccount { get; set; } public virtual SystemAccount SecondMasterAccount { get; set; } public virtual List AllSubAccounts { get; set; } public virtual List SecondarySubAccounts { get; set; } 

当我这样做时,我在表中获得4个FK,其中2个是自动生成的( SystemAccount_IDSystemAccount_ID1 )。 我甚至试图将MasterAccountSecondMasterAccount上的[InverseProperty]属性指向列表,每次都给我一个错误(编辑:它给我一个NullReferenceException )。

我知道我应该把它变成一个多对多的关系,但我很快就会面临一个截止日期,重构MasterAccountMasterAccountID的使用将超出截止日期。

我怎样才能让它发挥作用?

编辑:exception堆栈跟踪:

 System.NullReferenceException was unhandled by user code HResult=-2147467261 Message=Object reference not set to an instance of an object. Source=EntityFramework StackTrace: at System.Data.Entity.ModelConfiguration.Configuration.Types.EntityTypeConfiguration.Configure(EdmEntityType entityType, EdmModel model) at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.ConfigureEntities(EdmModel model) at System.Data.Entity.ModelConfiguration.Configuration.ModelConfiguration.Configure(EdmModel model) at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo) at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection) at System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer) at System.Data.Entity.Migrations.Extensions.DbContextExtensions.c__DisplayClass1.b__0(XmlWriter w) at System.Data.Entity.Migrations.Extensions.DbContextExtensions.GetModel(Action`1 writeXml) at System.Data.Entity.Migrations.Extensions.DbContextExtensions.GetModel(DbContext context) at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext) at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration) at System.Data.Entity.MigrateDatabaseToLatestVersion`2.InitializeDatabase(TContext context) at System.Data.Entity.Database.c__DisplayClass2`1.b__0(DbContext c) at System.Data.Entity.Internal.InternalContext.c__DisplayClass8.b__6() at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action) at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization() at System.Data.Entity.Database.Initialize(Boolean force) at Tests.Core.UI.SessionStartTests.ShouldSuccessfullyInitializeDatabase() in c:\Projects\Current\tests\Tests.Core\UI\StartTests.cs:line 72 InnerException: 

编辑2:当我使用Moho的建议时:

 System.Data.Entity.ModelConfiguration.ModelValidationException : One or more validation errors were detected during model generation: \tSystem.Data.Entity.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'SystemAccount_AllSubAccounts_Target' in relationship 'SystemAccount_AllSubAccounts'. Valid values for multiplicity for the Principal Role are '0..1' or '1'. \tSystem.Data.Entity.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'SystemAccount_AllSubAccounts_Source' in relationship 'SystemAccount_AllSubAccounts'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'. \tSystem.Data.Entity.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'SystemAccount_SecondarySubAccounts_Target' in relationship 'SystemAccount_SecondarySubAccounts'. Valid values for multiplicity for the Principal Role are '0..1' or '1'. \tSystem.Data.Entity.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'SystemAccount_SecondarySubAccounts_Source' in relationship 'SystemAccount_SecondarySubAccounts'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'. 

编辑3:我更新数据库的代码:

 Database.SetInitializer(new MigrateDatabaseToLatestVersion()); var db = new MyDbContext(); db.Database.Initialize(true); 

我的OnModelCreating方法:

 modelBuilder.Conventions.Remove(); modelBuilder.Entity().ToTable("ClientStatistics"); base.OnModelCreating(modelBuilder); 

我的Configuration文件:

 public Configuration() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } protected override void Seed(MyDbContext context) { } 

您是否尝试使用InverseProperty属性修饰集合属性?

 [InverseProperty( "MasterAccount" )] public virtual List AllSubAccounts { get; set; } [InverseProperty( "SecondMasterAccount" )] public virtual List SecondarySubAccounts { get; set; } 

这是一个适合我的演示:

 public class HierarchicalEntity { public int Id { get; set; } public string Description { get; set; } [ForeignKey( "PrimaryParent" )] public int? PrimaryParentId { get; set; } [ForeignKey( "SecondaryParent" )] public int? SecondaryParentId { get; set; } public virtual HierarchicalEntity PrimaryParent { get; set; } public virtual HierarchicalEntity SecondaryParent { get; set;} [InverseProperty( "PrimaryParent" )] public ICollection ChildrenViaPrimaryParent { get; set; } [InverseProperty( "SecondaryParent" )] public ICollection ChildrenViaSecondaryParent { get; set; } } 

多个自我引用

我现在用EF 5重现了这个问题。在应用Moho代码时,我得到完全相同的exception和堆栈跟踪以及编辑2中的exception。 EF 6不会出现此问题。因此,如果升级到EF 6是一个可以解决问题的选项。

如果您需要使用Fluent API映射而不是使用[InverseProperty]属性来使用EF 5,而无需例外。 您可以删除所有属性:

 public class SystemAccount { public int ID { get; set; } public int? MasterAccountID { get; set; } public int? SecondMasterAccountID { get; set; } public virtual SystemAccount MasterAccount { get; set; } public virtual SystemAccount SecondMasterAccount { get; set; } public virtual List AllSubAccounts { get; set; } public virtual List SecondarySubAccounts { get; set; } } 

与Fluent API的关系映射:

 modelBuilder.Entity() .HasOptional(s => s.MasterAccount) .WithMany(s => s.AllSubAccounts) .HasForeignKey(s => s.MasterAccountID); modelBuilder.Entity() .HasOptional(s => s.SecondMasterAccount) .WithMany(s => s.SecondarySubAccounts) .HasForeignKey(s => s.SecondMasterAccountID); 

因为模型的[InverseProperty]属性导致exception这一事实似乎是EF 5中的一个错误。该错误很可能与关系的自引用类型有关,因为通常在不同实体之间存在关系时,该属性可以正常工作。

我的解决方案基于我从@Slauma和@Moho获得的建议(+1给你们两个人的帮助!)。

确实, [InverseProperty]属性是缺少的,但是当我把它放在文件上时它就不起作用了。 然后,当我在一个全新的文件中尝试@ Moho的代码时,它仍然无效。 所以我将[ForeignKey]属性从ID字段转换为对象字段本身,即:

 public int? PrimaryParentId { get; set; } public int? SecondaryParentId { get; set; } [ForeignKey( "PrimaryParent" )] public virtual HierarchicalEntity PrimaryParent { get; set; } [ForeignKey( "SecondaryParent" )] public virtual HierarchicalEntity SecondaryParent { get; set;} 

最终工作。 但是当我尝试在我的SystemAccount类上执行此操作时,它将无法正常工作。 所以我最终做了以下步骤以使其工作:

  1. 从两个字段中注释掉列表对象,父记录和FK属性。
  2. 迁移数据库。 所有FK现在都下降了。
  3. 取消评论它
  4. 检查[InverseProperty]属性是否在列表对象上,并将[ForeignKey]属性放在virtual对象上。
  5. 迁移数据库。 唯一出现的FK就是那些我想成为FK的人!

我知道这是一个奇怪的解决方案,但只要它有效……