web-dev-qa-db-ja.com

EntityFramework Coreで部分クラスと部分OnModelCreatingメソッドを使用してDbContextを拡張する方法

EF Core DbFirstアプローチを使用しています。私のdbContextはScaffold-DbContextコマンドによって自動的に作成されます。

追加のDbSetsをdbContextに追加し、dbContextのOnModelCreatingメソッドに追加のコードを追加する必要がありますが、追加したコードの各スキャフォールディングが消去され、毎回追加する必要があります。

私がやりたいのは、別の部分的なdbContextクラスを作成し、protected override void OnModelCreating(ModelBuilder modelBuilder)を部分的としてマークすることです方法

しかし、エラーが発生します:

  1. 部分メソッドには、アクセス修飾子または仮想、抽象、オーバーライド、新規、シール、または外部修飾子を使用できません
  2. 部分メソッドには複数の実装宣言がない場合があります

擬似コードは次のとおりです。

MyDbContext1.cs-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-スカフォールディング後に毎回dbContextに追加したこのコード:

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

別の方法として、MyDbContextから継承する別のコンテキストクラスを作成し、実際にすべてのカスタムコードを含めます。次に、この新しいクラスをコンテキストとして使用します。この方法では、生成されたコードを更新する必要はありません。

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

すべての「パーツ」が単一のクラスになるため、部分クラスのメソッドをオーバーライドすることはできません。ただし、メインのOnModelCreatingで partial method を呼び出すことでこれを実現できます。このような:

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

彼らは[〜#〜] finally [〜#〜]これを修正しました!

ストアドプロシージャにHasNoKeyを追加する必要がありました(足場になっていないカスタムの戻り値型を使用)。

次のような部分クラスでOnModelCreatingPartialを実装できるようになりました。

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

足場のコンテキストファイルで-まさに最後に...

 OnModelCreatingPartial(modelBuilder);
0
Simon_Weaver