2017-11-22 5 views
0

So lösen Sie "Navigationseigenschaften können nur an einer einzelnen Beziehung teilnehmen." Fehler unter Fall?EF-Core 2.0 eins zu viele teilen die gleiche Tabelle

1 Unternehmen viele Milestone und MissionValueStory, wo Milestone und MissionValueStory teilen selben Tisch mit verschiedenen TypeId, und jeder von denen hat viele Übersetzung, wo verbinden mit companyInfoId nur

oder besser brechen die Beziehung zwischen Company und Unternehmen hat, und nur eine weitere Abfrage zum Abrufen von companyInfo ist sehr einfach?

public class Company 
 
    { 
 
     [key] 
 
     public long Id { get; set; } 
 

 
     public string Name { get; set; } 
 

 
     public virtual ICollection<CompanyInfo> Milestone { get; set; } //multi 
 

 
     public virtual ICollection<CompanyInfo> MissionValueStory { get; set; } //multi 
 
    } 
 

 
    public class CompanyInfo 
 
    { 
 
     [key] 
 
     public long Id { get; set; } 
 

 
     public long typeId { get; set; } 
 
     
 
     [Required] 
 
     public long CompanyId { get; set; } 
 
      
 
     public string Title { get; set; } 
 
     
 
     public string Text { get; set; } 
 
     
 
     [ForeignKey("CompanyId")] 
 
     public virtual Company Company { get; set; } 
 
     
 
     public ICollection<Translation> Translation { get; set; } 
 
    } 
 

 
    public class Translation 
 
    { 
 
     [key] 
 
     public long Id { get; set; } 
 
     
 
     public string Title { get; set; } 
 
     
 
     [Required] 
 
     public long CompanyInfoId { get; set; } 
 
     
 
     public string Language { get; set; } 
 
     
 
     [ForeignKey("CompanyInfoId")] 
 
     public virtual CompanyInfo CompanyInfo { get; set; } 
 
    } 
 

 
      modelBuilder.Entity<Company>() 
 
       .HasMany(e => e.Milestone) 
 
       .WithOne(t => t.Company) 
 
       .HasForeignKey(m => m.CompanyId).IsRequired() 
 
       .OnDelete(DeleteBehavior.Cascade); 
 

 

 
      modelBuilder.Entity<Company>() 
 
       .HasMany(e => e.MissionValueStory) 
 
       .WithOne(t => t.Company) 
 
       .HasForeignKey(m => m.CompanyId).IsRequired() 
 
       .OnDelete(DeleteBehavior.Cascade); 
 

 
      
 
      modelBuilder.Entity<CompanyInfo>() 
 
       .HasMany(e => e.Translation) 
 
       .WithOne(t => t.CompanyInfo).IsRequired();

+0

Also im Grunde eine 'CompanyInfo' ist eigher ein' Milestone' oder ein 'MissionValueStory' aber es ist nie beides? – grek40

Antwort

1

Was Sie versuchen, unterstützt zu Recht zu tun, ist es nicht. Zumindest in der Art, wie du das machst. Zum Glück gibt es eine ziemlich schmerzlose Lösung für Sie. Verwenden Sie Tabelle pro Hierarchie.

Ändern Sie die Klasse CompanyInfo, um eine abstrakte Klasse namens CompanyInfoBase zu sein, und lassen Sie es eine abstrakte Art sein. Machen Sie typeId abstrakt auf CompanyInfoBase.

zwei neue Klassen erstellen, die CompanyInfoBase implementieren:

public class MilestoneCompanyInfo : CompanyInfoBase 
{ 
    public override long typeId { get; set; } = MILESTONE_TYPE_ID; 
} 

public class MissionValueStoryCompanyInfo : CompanyInfoBase 
{ 
    public override long typeId { get; set; } = MISSION_VALUE_STORY_TYPE_ID; 
} 

wo MILESTONE_TYPE_ID und MISSION_VALUE_STORY_TYPE_ID irgendeine Art von vordefinierten Konstanten sind.

Verwenden Sie in Ihrem DbContext OnModelCreating typeId als Ihren Diskriminator.

Es wird in etwa so aussehen:

modelBuilder.Entity<CompanyInfoBase>() 
    .HasDiscriminator<long>(nameof(CompanyInfoBase.typeId)) 
    .HasValue<MilestoneCompanyInfo>(MILESTONE_TYPE_ID) 
    .HasValue<MissionValueStoryCompanyInfo>(MISSION_VALUE_STORY_TYPE_ID); 

Da Sie den Namen des Unternehmens sind zu ändern, es lohnt sich, die Tabellennamen Einstellung Ihrer vorhandenen db aufzunehmen. Etwas wie:

modelBuilder.Entity<CompanyInfoBase>().ToTable("CompanyInfos"); 

Hinweis auf andere Leser: Es ist nur erforderlich, um die Unterscheidungs ​​wie dieser aufgrund seiner Entscheidung zu definieren einen long zu verwenden. Wenn er es nur undefiniert belassen hat, behandelt EF Core das automatisch (indem er eine Spalte namens discriminator erstellt, die die konkreten Klassennamen enthält).

Hier ist ein Link auf die Erbschaft Referenzseite: https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/inheritance

Verwandte Themen