【问题标题】:Entity Framework 6 DBContext with only a subset of all tablesEntity Framework 6 DBContext 仅具有所有表的子集
【发布时间】:2017-08-31 09:33:21
【问题描述】:

我们有一个包含 770 个表的大型数据库,并希望使用 EF 6.1x 进行一些性能测试。

我们只想查询这 770 个表中的 5 个。是否可以创建一个只有 5-6 个实体/DBSet 的“轻量级”DBContext 而不是使用完整的 770 个表上下文?

当我们使用完整上下文时,一个包含 4 个连接的简单查询需要 45 秒。那44秒太长了。 我们使用的是代码优先(逆向工程)。

问题: 当我们创建完整上下文的这样一个“轻量级”版本(即仅 5 个表)时,EF 抱怨与这 5 个表有某种关联的所有其他实体都缺少键。我们只映射这 5 个表的键、属性和关系,而不映射其余表。

由于用 LINQ 编写的查询只查询 5 个表,EF 应该简单地忽略其他 765 个表,但它不会。 为什么不呢? LazyLoading=true/false 似乎与此无关。

注意:显然,可以在数据库中创建一个视图,该视图执行我们在代码中使用 LINQ 查询所做的事情。问题是它可以用上面的“轻” DbContext 来完成。

这里有上下文的“轻量级”版本:

public class ItemLookupContext : DbContext
{
    static ItemLookupContext()
    {
        Database.SetInitializer<ItemLookupContext>( null );
    }

    public ItemLookupContext()
        : base( "Name=ItemLookupContext" )
    {
        //Configuration.LazyLoadingEnabled = true;
    }

    public DbSet<Identity> Identities { get; set; }
    public DbSet<Item> Items { get; set; }
    public DbSet<Price> Prices { get; set; }
    public DbSet<Department> Departments { get; set; }
    public DbSet<Brand> Brands { get; set; }

    protected override void OnModelCreating( DbModelBuilder modelBuilder )
    {
        modelBuilder.Configurations.Add( new IdentityMap() );
        modelBuilder.Configurations.Add( new ItemMap() );
        modelBuilder.Configurations.Add( new PriceMap() );
        modelBuilder.Configurations.Add( new DepartmentMap() );
        modelBuilder.Configurations.Add( new BrandMap() );

        //ignore certain entitities to speed up loading?
        //does not work
        modelBuilder.Ignore<...>();
        modelBuilder.Ignore<...>();
        modelBuilder.Ignore<...>();
        modelBuilder.Ignore<...>();
        modelBuilder.Ignore<...>();
    }
}

【问题讨论】:

  • 这当然是可能的并且实际上是推荐的。在较大的数据库环境中,为表的子集提供多个不同的上下文通常会提高性能。
  • 一些代码将有助于理解您的问题,但我猜您会寻找类似stackoverflow.com/questions/17246069/… 的东西?
  • 是 exe 的第一个简单查询,即触发上下文构建的一个查询?
  • @DavidG:问题是当我创建一个包含所有表子集的上下文时,为什么 EF 会抱怨甚至不在该上下文中的实体?
  • @Dave 我最终使用了强大的 EntityFramework Reverse POCO Code First Generator 来生成类。希望这会有所帮助。

标签: c# .net sql-server entity-framework dbcontext


【解决方案1】:

你想尝试什么,比如作为 DDD 模式之一的“有界上下文”

所以,您可以查看 Julie Lerman 的这篇文章,Shrink EF Models with DDD Bounded Contexts

【讨论】:

    【解决方案2】:

    只需为您的表创建 DBContext。为了防止实体框架抱怨未映射的表,您已经关闭了应用程序中的数据库初始化。把它放在你的 global.asax/Startup.cs 中

    Database.SetInitializer<YourDbContext>(null);
    

    它告诉 EF 停止将您的实际数据库结构与您的 DbContext 进行比较。 这也意味着,如果有人更改了您的 EF 映射表,您将没有机会收到通知。

    【讨论】:

      【解决方案3】:

      A 类和 B 类之间存在多对一关系时:

      public class A
      {
         public B b {get; set;}
      }
      public class B
      {
          public ICollection<A> As {get; set;} 
      }
      

      并定义以下DbContext,EF自动DbSet&lt;B&gt;包含到DbContext

      public class MyContext : DbContext
      {
         ...
         public DbSet<A> As { get; set; }
      }
      

      所以,如果你想让你的光DbContext 不包含相关的DbSets,只需使用Ignore 方法:

      public class MyContext : DbContext
      {
         ...
         public DbSet<A> As { get; set; }
      
         protected override void OnModelCreating( DbModelBuilder modelBuilder )
         {
            modelBuilder.Ignore<B>();
         }
      }
      

      【讨论】:

      • 谢谢!可以反过来做吗?需要时调用 Include() 并让 EF 默认忽略所有 DBSet,而不是包含它们?
      • @John,如果你 Ignore 一个类,你不能将它与 Include() 一起使用。
      • 我的意思是:如果一个表有 45 个对其他 DBSet 的引用,我是否必须调用 Ignore() 45 次,或者是否有更简单的方法来排除大量相关集?
      • 这对我仍然不起作用。每个 Ignore'd DbSet 都会出现运行时异常。
      • @John:有什么例外?
      【解决方案4】:

      您似乎使用了 Entity Framework Power Tools 之类的工具来生成实体类和映射。这将为数据库中的每个表生成一个类、一个巨大的上下文、所有这些类的映射以及所有可能的关联。这太过分了。

      首先删除所有不需要的类和映射。然后删除与您剩下的几个类中已删除类的所有关联,不是原始外键字段。还要从上下文中删除所有 DbSet,除了您需要的少数几个。

      这种精简的类模型本身将是一致的。它不会与数据库中的所有实体关联,但可以通过引用上下文之外的实体的外键值进行过滤。

      如果您以任何其他方式生成/创建代码,这仍然是症结所在:仅使用类模型中其他类的导航属性。对于其他引用,请使用原始外键属性。

      【讨论】:

      • 我担心有人会这么建议。我确实使用了电动工具,但我从一些生成的实体创建的 dbcontext 只是我们需要的众多 dbcontext 之一。从您写的内容来看,我认为不可能在多个上下文中使用相同的实体类。但是我需要为每个 dbcontext 一次又一次地创建相同的实体类吗?那么 dbcontext A 的 Item1.cs,dbcontext B 的 Item2.cs 等等?
      • 是的,基本上是这样。但我认为您应该尝试创建更大的上下文,以涵盖数据库的合理不同的聚合并服务于多个任务领域。因此,您可以减少重叠类的数量。 EntityFramework Reverse POCO Code First Generator 在这里可能会有所帮助。
      • 您可以在不同的 DbContext 中使用相同的实体类,只要您创建一个单独的 EntityTypeConfiguration&lt;...&gt; 映射,该映射对于您不希望当前 DbContext 尝试的每个导航属性都有 Ignore(&lt;UnwantedReferenceHere&gt;);映射。
      猜你喜欢
      • 1970-01-01
      • 2016-08-03
      • 1970-01-01
      • 2014-05-04
      • 2021-02-05
      • 2021-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多