1

Ich habe zwei Einheiten User und Profile. Jede dieser Entitäten erbt von einer Entity Klasse, die eine Id Eigenschaft enthält. Die Beziehung zwischen dem Benutzer und dem Profil ist eine Eins-zu-Eins-Beziehung. Ich versuche, die gleiche ID zu verwenden, die für die Benutzer-Entität erstellt wurde, die ID für die Profil-Entität, d. H. User.Id == Profile.Id.Entity Core FluentAPI - Eine ID als Primär- und Fremdschlüssel

Ich habe versucht, dies mit FluentAPI zu tun, aber ich kann nicht. Ich habe diese question gelesen und lese auch diese post, aber ich bin immer noch nicht in der Lage, eine Lösung für mein Problem zu finden. Hier

ist der Code für meine Entitäten:

public class Entity<TKey> : IEntity 
{ 
    /// <summary> 
    /// Unique identifier for this entity. 
    /// </summary> 
    public virtual int Id { get; set; } 
} 

public class User : Entity<int> 
{ 
    public virtual Profile ProfileItem { get; set; } 
} 

public class Profile : Entity<int> 
{ 

} 

Hier meine Versuche sind so weit, in dem alle fehlgeschlagen:

  • Diese Zuordnung einer ProfileItemId in der User Tabelle erzeugt:

    modelBuilder.Entity<User>().HasOne(u => u.ProfileItem) 
        .WithOne() 
        .HasForeignKey<Profile>(p => p.Id) 
        .IsRequired() 
        .OnDelete(DeleteBehavior.Cascade); 
    
  • Ich habe versucht, ein in Vers Navigationseigenschaft in der Profile Einheit für User. Die User Tabelle korrekt abgebildet, sondern eine UserId Säule wurde die Profile Tabelle hinzugefügt:

    modeBuilder.Entity<User>().HasOne(u => u.ProfileItem) 
        .WithOne(u => u.User) 
        .HasForeignKey<Profile>(p => p.Id) 
        .IsRequired() 
        .OnDelete(DeleteBehavior.Cascade); 
    

Die einzige Lösung für dieses Problem wie in der Frage berichtet, dass ich bereits erwähnt, ist, dass Sie hinzufügen müssen eine inverse Eigenschaft und verwenden Sie dann Datenanmerkungen. Ich habe folgendes versucht und es hat funktioniert:

public class Entity<TKey> : IEntity 
{ 
    /// <summary> 
    /// Unique identifier for this entity. 
    /// </summary> 
    public virtual int Id { get; set; } 
} 

public class User : Entity<int> 
{ 
    [InverseProperty("User")] 
    public virtual Profile ProfileItem { get; set; } 
} 

public class Profile : Entity<int> 
{ 
    [ForeignKey("Id")] 
    public virtual User User { get; set; } 
} 

Wie bekomme ich das gleiche um mit FluentAPI zu arbeiten?

+1

Alle Ihre Versuche außer der letzten (Doppel-Mapping) sind korrekt und sollten funktionieren. Stellen Sie nur sicher, wenn Sie '.WithOne()' verwenden, gibt es keine Referenznavigationseigenschaft 'User' in' Profile'. Versuchen Sie, das Problem in einem sauberen Projekt zu reproduzieren (weil ich nicht kann - alles funktioniert wie erwartet) und wahrscheinlich finden Sie die Ursache. –

+0

Wenn ich die Benutzereigenschaft aus dem Profil entferne, wird eine Spalte ProfileItemId in der Benutzertabelle erstellt. – ykh

+0

Ich entfernte die dritte Studie von meiner Frage ... – ykh

Antwort

0

Was @Ivan sagte, war richtig. In dem von mir geposteten Beispiel habe ich die Zuordnungen für das OnModelCreating-Ereignis erstellt, aber in meinem tatsächlichen Code habe ich eine Basisklasse für das Mapping verwendet, und das war das Problem.

Hier ist meine aktuellen Code, der das Problem erzeugt:

  • Eine Basisklasse für Entitätszuordnung

    public class EntityTypeConfigurationBase<T> : IEntityTypeConfiguration<T> where T : class, IEntity 
    { 
        private bool BIgnoreBaseProps = true; 
    
        public EntityTypeConfigurationBase(bool bIgnoreBaseProps = true) : base() 
        { 
         BIgnoreBaseProps = bIgnoreBaseProps; 
        } 
    
        public void Configure(EntityTypeBuilder<T> builder) 
        { 
         if (BIgnoreBaseProps) 
         { 
          builder.Ignore(x => x.State); 
          builder.Ignore(x => x.AssociationState); 
         } 
        } 
    } 
    
  • Meine Abbildungsklassen

    public class UserMap : EntityTypeConfigurationBase<User> 
    { 
    
        new public void Configure(EntityTypeBuilder<User> builder) 
        { 
    
        builder.HasKey(u => u.Id); 
        builder 
         .HasOne(u => u.ProfileItem) 
         .WithOne() 
         .HasForeignKey<Profile>(p => p.Id) 
         .IsRequired() 
         .OnDelete(DeleteBehavior.Cascade); 
        builder.ToTable("User"); 
    
        base.Configure(builder); 
        } 
    } 
    

Die Frage war in der Karte ping-Klasse in der Configure-Methode. In der Basisklasse musste ich einige gemeinsame Eigenschaften ignorieren, und in den Mapping-Klassen musste ich meine benutzerdefinierten Zuordnungen vornehmen. Die verwendete Methode heißt Configure, die für das Mapping implementiert werden muss. Da derselbe Methodenname sowohl für die Basis als auch für die abgeleiteten Klassen verwendet wird, führte dies zu einem doppelten Aufruf. Der erste Aufruf war für die Basistyp-Methode und der zweite für die Mapping-Klassen. Das Mapping wurde zweimal durchgeführt und der Fremdschlüssel (mein Problem) wurde beim ersten Mapping generiert.

Die Lösung für dieses Problem bestand darin, die Basistypmethode als virtual zu markieren und dann die Methode für den Basistyp zu überschreiben. Der Basistyp-Methodenaufruf übernimmt das gleiche Objekt ModelBuilder und dupliziert das Mapping nicht erneut.

Verwandte Themen