web-dev-qa-db-fra.com

Comment étendre DbContext avec une classe partielle et une méthode OnModelCreating partielle dans EntityFramework Core

J'utilise l'approche EF Core DbFirst. Mon dbContext est créé automatiquement par la commande Scaffold-DbContext.

J'ai besoin d'ajouter des DbSets supplémentaires dans un dbContext et d'ajouter à la méthode OnModelCreating de dbContext du code supplémentaire mais après chaque échafaudage, le code ajouté est effacé et je dois l'ajouter à chaque fois.

Ce que je veux faire est de créer une autre classe dbContext partielle et de marquer override protégé void OnModelCreating (ModelBuilder modelBuilder) comme partiel méthode

mais obtenez des erreurs:

  1. ne méthode partielle ne peut pas avoir de modificateurs d'accès ou les modificateurs virtuels, abstraits, de remplacement, nouveaux, scellés ou externes.
  2. ne méthode partielle peut ne pas avoir plusieurs déclarations d'implémentation

Voici un pseudo code:

MyDbContext1.cs - généré par Scaffold-DbContext

public partial class MyDbContext : DbContext
    {
        public MyDbContext()
        {
        }

        public MyDbContext(DbContextOptions<MyDbContext> options)
            : base(options)
        {
        }

        public virtual DbSet<Client> Clients { get; set; }

        protected override partial void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Client>(entity =>
            {
                // ... some code
            }
        }
    }

MyDbContext2.cs - ce code que j'ai ajouté à chaque fois dans dbContext après l'échafaudage:

public partial class MyDbContext
    {
        public virtual DbSet<JustAnotherEntity> AnotherEntity { get; set; }

        protected override partial void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<JustAnotherEntity>(entity =>
            {
                entity.HasKey(e => new {e.Id, e.IdAction, e.IdState})
                    .ForSqlServerIsClustered(false);
            });
        }
    }
9
Dmitry Stepanov

Une alternative serait de créer une autre classe de contexte héritant de MyDbContext qui inclut en fait tout le code personnalisé. puis utilisez cette nouvelle classe comme contexte. De cette façon, il n'est pas nécessaire de mettre à jour le code généré.

public class MyDbContext2 : MyDbContext 
{
    public MyDbContext2()
    {
    }

    public MyDbContext2(DbContextOptions<MyDbContext> options)
        : base(options)
    {
    }

    public virtual DbSet<JustAnotherEntity> AnotherEntity { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<JustAnotherEntity>(entity =>
        {
            entity.HasKey(e => new {e.Id, e.IdAction, e.IdState})
                .ForSqlServerIsClustered(false);
        });
    }
}
18
bakka

Vous ne pouvez pas remplacer des méthodes dans une classe partielle car toutes les "parties" deviennent une seule classe. Mais vous pouvez accomplir cela en ayant l'appel principal OnModelCreating a méthode partielle . Comme ça:

public partial class Db : DbContext
{
    partial void OnModelCreating2(ModelBuilder modelBuilder)
    {
       //additional config
    }
}

public partial class Db : DbContext
{

    public DbSet<Person> Persons { get; set; }

    partial void OnModelCreating2(ModelBuilder modelBuilder);
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        OnModelCreating2(modelBuilder);
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=localhost;database=efcore2test;integrated security=true");
        base.OnConfiguring(optionsBuilder);
    }
}

EFCore 3

Ils ENFIN ont corrigé cela!

J'avais besoin d'ajouter HasNoKey pour une procédure stockée (avec un type de retour personnalisé qui n'est pas échafaudé).

Vous pouvez maintenant implémenter OnModelCreatingPartial dans une classe partielle comme celle-ci:

public partial class RRStoreContext : DbContext
{
    partial void OnModelCreatingPartial(ModelBuilder builder)
    {
        builder.Entity<RepeatOrderSummaryView>().HasNoKey();
    }
}

Dans le fichier de contexte échafaudé - tout à la fin ...

 OnModelCreatingPartial(modelBuilder);
0
Simon_Weaver