web-dev-qa-db-fra.com

Entity Framework Core 2.0: comment configurer une fois la classe de base abstraite

J'ai un modèle de base:

public abstract class Status
{
     public string updateUserName { get; set; }
}

Puis un modèle qui étend le modèle de base défini ci-dessus:

public class Item : Status
{
     public int Id { get; set; }
     public string Description { get; set; }
}

Ensuite, j'ai défini des classes de configuration pour chacune:

public class ItemConfiguration : IEntityTypeConfiguration<Item>
{
    public void Configure(EntityTypeBuilder<Item> builder)
    {
        builder.ToTable("Item", "dbo").HasKey(c => c.Id);
        builder.Property(c => c.Description).IsRequired().HasMaxLength(100);
    }
}

public class StatusConfiguration : IEntityTypeConfiguration<Status>
{
    public void Configure(EntityTypeBuilder<Status> builder)
    {
        builder.Property(c => c.updateUserName).IsRequired().HasMaxLength(50);
    }

Maintenant, j'ai la classe de contexte suivante:

public class TestDbContext : DbContext
{
    public TestDbContext(DbContextOptions<TestDbContext> options) : base(options)
    {
    }

    public DbSet<Item> Item { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfiguration(new ItemConfiguration());
    }
}

J'essaie de comprendre comment appliquer les configurations de modèle d'état définies dans la classe StatusConfiguration à tous les modèles qui s'y étendent (un seul dans cet exemple: Article). Je voudrais éviter de définir la même configuration de modèle d'état à chaque fois qu'elle est utilisée. Le modèle d'état sera essentiellement des métadonnées associées à chaque enregistrement d'élément (c'est-à-dire une table d'élément dans la base de données contenant toutes les propriétés définies dans les deux modèles; rien de plus et rien de moins).

Par exemple, mon implémentation actuelle est la classe ItemConfiguration suivante sans utiliser la classe StatusConfiguration:

public class ItemConfiguration : IEntityTypeConfiguration<Item>
{
    public void Configure(EntityTypeBuilder<Item> builder)
    {
        builder.ToTable("Item", "dbo").HasKey(c => c.Id);
        builder.Property(c => c.Description).IsRequired().HasMaxLength(100);
        builder.Property(c => c.updateUserName).IsRequired().HasMaxLength(50);
    }
}

Cette implémentation actuelle fonctionne correctement et migre vers la base de données comme prévu. Je cherche simplement un moyen plus gérable d'aller de l'avant.

Mon hypothèse est que je pourrais étendre la classe ItemConfiguration pour inclure la classe StatusConfiguration mais ne peux pas trouver un exemple de cette méthode en ligne. J'espère que quelqu'un avec un peu plus d'expérience pourrait bien me diriger dans la bonne direction?

Faites-moi savoir si des informations supplémentaires seraient utiles.

10
TheDirtyJenks

Si je comprends bien, le Status est juste une classe de base et non une entité de base participant à Héritage de base de données =.

Dans ce cas, il est important de ne jamais faire référence à la classe Status directement à l'intérieur du modèle et de la configuration de l'entité, c'est-à-dire pas de DbSet<Status>, Pas de propriétés de navigation de type Status ou ICollection<Status> , pas d'appels modelBuilder.Entity<Status>() et pas IEntityTypeConfiguration<Status>.

Au lieu de cela, vous devez toujours vous référer aux types concrets héritant de Status. Afin de réutiliser le code de configuration, vous devez utiliser des méthodes ou classes génériques contraintes et transmettre les types d'entités concrètes.

Puisque vous utilisez des classes IEntityTypeConfiguration, le plus naturel est probablement de rendre votre classe StatusConfiguration générique:

public class StatusConfiguration<TEntity> : IEntityTypeConfiguration<TEntity>
    where TEntity : Status
{
    public virtual void Configure(EntityTypeBuilder<TEntity> builder)
    {
        builder.Property(c => c.updateUserName).IsRequired().HasMaxLength(50);
    }
}

et laissez les classes de configuration d'entité dérivées en dériver:

public class ItemConfiguration : StatusConfiguration<Item>
{
    public override void Configure(EntityTypeBuilder<Item> builder)
    {
        base.Configure(builder); // <--
        builder.ToTable("Item", "dbo").HasKey(c => c.Id);
        builder.Property(c => c.Description).IsRequired().HasMaxLength(100);
    }
}
28
Ivan Stoev