Come risolvere "Le proprietà di navigazione possono partecipare solo a una singola relazione". errore sul caso di sotto?
1 azienda ha molte Milestone e MissionValueStory, dove Milestone e MissionValueStory condividono la stessa tabella con diversi ID tipo, e ognuno di questi ha molte traduzioni in cui si collega solo con CompanyInfoId
O MEGLIO interrompi la relazione tra companyInfo e company, e solo un'altra query per recuperare companyInfo è molto semplice?
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();
Quello che stai cercando di fare è legittimamente non supportato. Almeno nel modo in cui stai facendo questo. Fortunatamente c'è una soluzione abbastanza indolore per te. Usa tabella per gerarchia.
Cambia la classe CompanyInfo
in una classe astratta chiamata CompanyInfoBase
e lascia che sia un tipo astratto. Crea typeId
abstract su CompanyInfoBase.
Creare due nuove classi che implementano CompanyInfoBase:
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;
}
dove MILESTONE_TYPE_ID
e MISSION_VALUE_STORY_TYPE_ID
sono una sorta di costanti predefinite.
Quindi, nel tuo OnModelCreating di DbContext, usa typeId come discriminatore.
Assomiglierà a qualcosa del genere:
modelBuilder.Entity<CompanyInfoBase>()
.HasDiscriminator<long>(nameof(CompanyInfoBase.typeId))
.HasValue<MilestoneCompanyInfo>(MILESTONE_TYPE_ID)
.HasValue<MissionValueStoryCompanyInfo>(MISSION_VALUE_STORY_TYPE_ID);
Dal momento che stai cambiando il nome dell'entità, vale la pena di impostare il nome della tabella per sistemare il tuo db esistente. Qualcosa di simile a:
modelBuilder.Entity<CompanyInfoBase>().ToTable("CompanyInfos");
Nota per altri lettori: è solo necessario definire il discriminatore come questo a causa della sua decisione di usare un long
. Se l'avesse appena lasciato indefinito, EF Core ne gestirà automaticamente (creando una colonna denominata discriminator che contiene i nomi di classe concreti).
Ecco un link alla pagina di riferimento dell'ereditarietà: https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/inheritance