代码之家  ›  专栏  ›  技术社区  ›  Derviş Kayımbaşıoğlu

根据拆分DbContext

  •  2
  • Derviş Kayımbaşıoğlu  · 技术社区  · 8 年前

    我想把我的 DbContext 类,这样每个模块都有自己的类,我相信这会使工作更简单,错误更多,并降低代码复杂性。

    我相信我以前在谷歌上看到过它,但没有找到它。

    我的 数据库上下文 位于基础结构层,我的类位于域上下文中。这不是问题。我想将映射和配置分离到单独的类中。我的 数据库上下文 将保持不变,除非将其拆分。

    我将代码peaces标记为我愿意拆分为以下几部分:

    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的确切方法。 我需要一种方法来做这件事。你能给我提供解决方案吗?

    2 回复  |  直到 8 年前
        1
  •  7
  •   Sefe    8 年前

    你首先要弄清楚你说的分裂是什么意思 DbContext . 您说这是一个分离关注点的问题,所以您应该首先决定要分离哪些关注点。这个 数据库上下文 处理将数据库表映射到对象模型的问题,因此它可以执行与此相关的所有操作。关注点分离的另一个目的是不要将关注点分割成碎片,因为这也会增加程序的复杂性。

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

    除此之外,还有一些方法可以“拆分”您的 数据库上下文 分成几部分:

    使 数据库上下文 部分类

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

    使用实体类型配置类

    可以使用派生自的类,使用fluent API配置实体类 EntityTypeConfiguration (或实施 IEntityTypeConfiguration interface 在里面net Core 2.0),它允许您在 数据库上下文 . 当您拥有大量实体类时,这实际上有助于提高可管理性,其中 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 达到同样的效果。

        2
  •  0
  •   Usama Tabbassum    4 年前

    您可以使用EF Core power tool,它将自动处理。 enter image description here