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

时间:2014-02-17 21:31:57

标签: c# entity-framework ef-code-first entity-framework-5

我有一个名为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<SystemAccount> AllSubAccounts { get; set; }

public virtual List<SystemAccount> SecondarySubAccounts { get; set; }

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

我知道我应该将其变为多对多关系,但我很快就会面临截止日期,并重构NullReferenceException和{{1}的用法我会超越截止日期。

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

编辑:异常堆栈跟踪:

MasterAccount

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

MasterAccountID

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

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.<GetModel>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.<SetInitializerInternal>b__0(DbContext c)
       at System.Data.Entity.Internal.InternalContext.<>c__DisplayClass8.<PerformDatabaseInitialization>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: 

我的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 '*'. 方法:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyDbContext, Configuration>());
var db = new MyDbContext();
db.Database.Initialize(true);

我的OnModelCreating文件:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

modelBuilder.Entity<ClientStatisticsView>().ToTable("ClientStatistics");

base.OnModelCreating(modelBuilder);

3 个答案:

答案 0 :(得分:4)

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

[InverseProperty( "MasterAccount" )]
public virtual List<SystemAccount> AllSubAccounts { get; set; }

[InverseProperty( "SecondMasterAccount" )]
public virtual List<SystemAccount> 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<HierarchicalEntity> ChildrenViaPrimaryParent { get; set; }

    [InverseProperty( "SecondaryParent" )]
    public ICollection<HierarchicalEntity> ChildrenViaSecondaryParent { get; set; }
}

multiple self-references

答案 1 :(得分:3)

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

如果你需要使用Fluent API映射坚持使用EF 5,而不是使用[InverseProperty]属性为我工作,没有例外。您可以删除所有属性:

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<SystemAccount> AllSubAccounts { get; set; }
    public virtual List<SystemAccount> SecondarySubAccounts { get; set; }
}

与Fluent API的关系映射:

modelBuilder.Entity<SystemAccount>()
    .HasOptional(s => s.MasterAccount)
    .WithMany(s => s.AllSubAccounts)
    .HasForeignKey(s => s.MasterAccountID);

modelBuilder.Entity<SystemAccount>()
    .HasOptional(s => s.SecondMasterAccount)
    .WithMany(s => s.SecondarySubAccounts)
    .HasForeignKey(s => s.SecondMasterAccountID);

与您的模型的[InverseProperty]属性导致异常的事实似乎是EF 5中的错误。该错误很可能与关系的自引用类型有关,因为通常与不同实体之间的关系属性没有问题。

答案 2 :(得分:1)

我的解决方案基于我从@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的人!
  6. 我知道这是一个奇怪的解决方案,但只要它有效......