根据拆分 DbContext

Posted

技术标签:

【中文标题】根据拆分 DbContext【英文标题】:Splitting DbContext according to 【发布时间】:2018-05-27 06:40:05 【问题描述】:

我想将我的DbContext 类拆分成多个部分,以便每个模块都有自己的类,我相信这可以让工作更轻松、更多错误宝座并降低代码复杂性。

我相信我在过去的某个地方在谷歌搜索时看到了它,但是没有找到它。

我的DbContext 在基础设施层中,我的类在域上下文中。那不是问题。我想将映射和配置分成单独的类。我的DbContext 将保持不变,但会被拆分。

我在下面标记了我愿意拆分的代码和平:

public class WestCoreDbContext : DbContext

    public WestCoreDbContext(DbContextOptions<WestCoreDbContext> options) : base(options)
    

    
    #region WOULD LIKE TO SPLIT THIS PART
    public virtual DbSet<SoftwareTest> SoftwareTests  get; set; 
    public virtual DbSet<SoftwareTestCase> SoftwareTestCases  get; set; 
    public virtual DbSet<SoftwareTestCaseStep> SoftwareTestCaseSteps  get; set; 
    public virtual DbSet<SoftwareTestCaseStepResult> SoftwareTestCaseStepResults  get; set; 

    public virtual DbSet<Position> Positions  get; set; 
    #endregion

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    

        #region WOULD LIKE TO SPLIT THIS PART
        SoftwareTestMapping(modelBuilder);
        SoftwareTestCaseMapping(modelBuilder);
        SoftwareTestCaseMapping(modelBuilder);
        SoftwareTestCaseStepMapping(modelBuilder);
        SoftwareTestCaseStepResultsMapping(modelBuilder);
        PositionMapping(modelBuilder);

        RelationshipsMapping(modelBuilder);
        #endregion

        modelBuilder.MyOracleNamingConventions();

        base.OnModelCreating(modelBuilder);
    

    #region WOULD LIKE TO SPLIT THIS PART

    private void SoftwareTestMapping(ModelBuilder modelBuilder)
    
        modelBuilder.Entity<SoftwareTest>();
    

    private void SoftwareTestCaseMapping(ModelBuilder modelBuilder)
    
        modelBuilder.Entity<SoftwareTestCase>();
    

    private void SoftwareTestCaseStepMapping(ModelBuilder modelBuilder)
    
        modelBuilder.Entity<SoftwareTestCaseStep>();
    

    private void PositionMapping(ModelBuilder modelBuilder)
    
        modelBuilder.Entity<Position>();
    

    private void SoftwareTestCaseStepResultsMapping(ModelBuilder modelBuilder)
    
        modelBuilder.Entity<SoftwareTestCaseStepResult>();
    

    private void RelationshipsMapping(ModelBuilder modelBuilder)
    
        modelBuilder.Entity<SoftwareTest>().HasMany(x => x.SoftwareTestCases).WithOne(op => op.SoftwareTest).IsRequired().HasForeignKey(@"StId");
        modelBuilder.Entity<SoftwareTestCase>().HasOne(x => x.SoftwareTest).WithMany(op => op.SoftwareTestCases).IsRequired().HasForeignKey(@"StId");

        modelBuilder.Entity<SoftwareTestCase>().HasMany(x => x.SoftwareTestCaseSteps).WithOne(op => op.SoftwareTestCase).IsRequired().HasForeignKey("StcId");
        modelBuilder.Entity<SoftwareTestCaseStep>().HasOne(x => x.SoftwareTestCase).WithMany(op => op.SoftwareTestCaseSteps).IsRequired().HasForeignKey("StcId");

        modelBuilder.Entity<SoftwareTestCaseStep>().HasMany(x => x.SoftwareTestCaseStepResults).WithOne(op => op.SoftwareTestCaseStep).IsRequired().HasForeignKey("StcsId");
        modelBuilder.Entity<SoftwareTestCaseStepResult>().HasOne(x => x.SoftwareTestCaseStep).WithMany(op => op.SoftwareTestCaseStepResults).IsRequired().HasForeignKey("StcsId");
    
    #endregion

    public bool HasChanges()
    
        return ChangeTracker.Entries().Any(e => e.State == EntityState.Added || e.State == EntityState.Modified || e.State == EntityState.Deleted);
    

    ...


我不知道拆分 DbContext 的确切方法。 我需要一种方法来做到这一点。你能给我解决办法吗?

【问题讨论】:

那么你的问题是什么? 我不确定如何将 DBContext 拆分为更小的部分。我想有 1 个 DbContext 但有更小的部分。它对我的关注问题的分离。 你尝试过吗?只需复制这个类,给它一个新名称并删除你不需要的部分。 您似乎尝试在一个类中执行此操作,这确实有效,但需要重构。最简单的方法是拥有多个 DbContext 类,因为您不能使属性在一个类中不可用。如果您确实有最低工作要求,则接口可能是一种解决方案。但是请注意,这种方法几乎不会影响代码复杂性,并且只能使用几个类来保存模型构建(如果您不想重构 BL 以不使用 DbSet 属性) 请注意,context.Set&lt;T&gt;() 将始终提供对上下文中所有映射实体的访问。这可能是少数情况下需要额外的工作单元/通用存储库抽象层的情况之一。另请注意,属于一个上下文类的编译模型在每个应用程序生命周期内只会构建一次。您不能为每个实例编译模型(嗯,这是可能的,但不推荐)。因此,如果这就是您所说的“拆分”的意思,请注意您需要不同的上下文 【参考方案1】:

您首先要清楚拆分DbContext 的含义。您说这是一个关注点分离的问题,所以您应该首先决定要分离哪些关注点。 DbContext 处理将数据库表映射到对象模型的问题,因此它执行与此相关的所有事情是有意义的。关注点分离的另一端是不要将关注点拆分成多个部分,因为这也会增加程序的复杂性。

良好的关注点分离是将DbContext 保持在一起,让它完成将数据库映射到对象模型的基本工作。其他任务(例如对数据库的专门查询)将封装在使用 DbContext 的存储库中,这还允许您从实际的实体框架实现中抽象出业务层。

除此之外,还有一些方法可以将您的DbContext“拆分”为多个部分:

DbContext 设为部分类

您可以将WestCoreDbContext 设为partial class 并将其内容拆分到多个代码文件中。您应该清楚编译后的输出将完全相同,因此您并没有真正改善 OOP 意义上的关注点分离。您还可以争论是否在没有充分理由的情况下将单个类拆分为多个代码文件(例如部分自动生成的类)实际上会增加或减少代码的可管理性。这是您必须自己做出的决定。

使用实体类型配置类

您可以使用派生自EntityTypeConfiguration 的类(或在.net Core 2.0 中实现IEntityTypeConfiguration interface)使用流式API 配置您的实体类,这样您就可以在DbContext 之外配置您的实体类。当您拥有大量实体类时,这实际上有助于提高可管理性,而 OnModelCreating 方法会变得很长。

在您的情况下,这在 .net Core 2.0 中看起来像这样(我已经简化了您的示例):

public class WestCoreDbContext : DbContext

    public WestCoreDbContext(DbContextOptions<WestCoreDbContext> options) : base(options)
    

    

    public virtual DbSet<SoftwareTestCase> SoftwareTestCases  get; set; 
    //Define further DbSets

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    
        modelBuilder.ApplyConfiguration(new SoftwareTestCaseConfiguration());
        //Apply further configurations

        modelBuilder.MyOracleNamingConventions();

        base.OnModelCreating(modelBuilder);
    

    public bool HasChanges()
    
        return ChangeTracker.Entries().Any(e => e.State == EntityState.Added || e.State == EntityState.Modified || e.State == EntityState.Deleted);
    


//This configuration class is separated from the WestCoreDbContext and can go into a separate code file
internal class SoftwareTestCaseConfiguration : IEntityTypeConfiguration<SoftwareTestCase>

    public void Configure(EntityTypeBuilder<SoftwareTestCase> modelBuilder)
    
        modelBuilder.Entity<SoftwareTestCase>().HasOne(x => x.SoftwareTest).WithMany(op => op.SoftwareTestCases).IsRequired().HasForeignKey(@"StId");
        modelBuilder.Entity<SoftwareTestCase>().HasMany(x => x.SoftwareTestCaseSteps).WithOne(op => op.SoftwareTestCase).IsRequired().HasForeignKey("StcId");
    

如果您不在 .net Core 2.0 上,请检查 this Q&A 以获得相同的结果。

【讨论】:

.Net Core 是否仍然允许 modelBuilder.Configurations.AddFromAssembly(typeof(SoftwareTestCaseConfiguration).Assembly); 之类的东西收集类库项目的所有配置? @grek40:查看the official documentation。 ModelBuilder 或其扩展方法上没有类似的东西。 “实体类型配置类”正是我要找的。非常感谢您的宝贵时间。我正在考虑将 dbSets 放入部分类 public virtual DbSet<softwaretestcase> SoftwareTestCases get;放; </softwaretestcase>【参考方案2】:

您可以使用 EF Core 电动工具,它会自动处理。

【讨论】:

以上是关于根据拆分 DbContext的主要内容,如果未能解决你的问题,请参考以下文章

根据日期拆分数据框

批量--10---根据set数拆分文件

批量--10---根据set数拆分文件

根据第一个点 (.) 拆分方程

根据位掩码拆分多个字节

将excel根据列名称拆分成多个文件