如何在EntityFramework Core中使用部分类和部分OnModelCreating方法扩展DbContext

时间:2018-09-05 09:46:35

标签: c# entity-framework entity-framework-core partial partial-classes

我正在使用EF Core DbFirst方法。我的dbContext是由Scaffold-DbContext命令自动创建的。

我需要向dbContext中添加其他DbSet,并向dbContext的OnModelCreating方法中添加一些其他代码,但是在删除每个添加的代码的脚手架之后,我必须再次添加它。

我想做的是创建另一个局部dbContext类,并将 受保护的重写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);
            });
        }
    }

3 个答案:

答案 0 :(得分:8)

一种替代方法是创建另一个从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);
        });
    }
}

答案 1 :(得分:6)

EFCore 3-他们最终解决了这个问题!

您现在可以在部分类中实现OnModelCreatingPartial,如下所示:

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

如果您查看生成的上下文文件-在最后,您将看到...

 OnModelCreatingPartial(modelBuilder);

注意:这是必要的,因为我需要为存储过程手动添加HasNoKey(使用自定义返回类型,否则该类型就不会被支架)。

答案 2 :(得分:4)

您不能覆盖部分类中的方法,因为所有“部分”都成为一个类。但是您可以通过使主要的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);
    }
}