OnModelCreating 即使对于新上下文也只调用一次

问题描述 投票:0回答:3

我有多个相同但内容不同的 SQL Server 表。在编写代码优先 EF6 程序时,我尝试为每个程序重用相同的数据库上下文,并将表名称传递给上下文构造函数。

但是,虽然每次都会调用构造函数,但尽管每次都是从 new 创建数据库上下文,但 OnModelCreating 方法仅被调用一次。我该如何重置?

我尝试过使用 AsNoTracking 并阅读了禁用 ModelCaching 的内容,但无法找到如何执行此操作或这是否是最佳方法。 MSDN 甚至说“可以通过在给定的 ModelBuidler[原文如此] 上设置 ModelCaching 属性来禁用此缓存”,但它不存在。

这是我的数据库上下文:

public partial class MissingContext : DbContext
{
    private string tableName = "";
    public MissingContext(string tableName) : base("name=MissingContext")
    {
        this.tableName = tableName;
    }

    public virtual DbSet<MissingData> MissingDataSet { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MissingData>()
           .ToTable(this.tableName);
    }
}

这是我使用它的代码:

List<MissingData> missingData=null;
string[] inputTables="TABLEA;TABLEB;TABLEC".Split(';');
foreach (string table in inputTables)
{
    logger.Info($"Processing {table}");
    missingData = null;

    MissingContext db = new MissingContext(table);
    var query = from d in db.MissingDataSet.AsNoTracking()
                select d;
    missingData = query.ToList();
}

在运行时,表总是具有正确的 TABLEA、TABLEB、TABLEC,并且它被传递到数据库上下文构造函数,但是 OnModelCreating 仅在第一个循环项中调用一次,因此查询对象生成的 SQL 始终从 TABLEA 中选择:

SELECT 
[Extent1].[id] AS [id], 
[Extent1].[OrganisationName] AS [OrganisationName] 
FROM [dbo].[**TABLEA**] AS [Extent1]

*如果任何代码看起来错误,我会重命名一些变量,因为它们对业务敏感。

c# entity-framework entity-framework-6
3个回答
5
投票

OnModelCreating
只会被调用一次,这是默认行为。

根据OnModelCreating文档。

通常,仅在创建派生上下文的第一个实例时调用此方法一次。然后,该上下文的模型将被缓存,并且适用于应用程序域中该上下文的所有其他实例。可以通过在给定 ModelBuidler 上设置 ModelCaching 属性来禁用此缓存,但请注意,这会严重降低性能。通过直接使用 DbModelBuilder 和 DbContextFactory 类提供对缓存的更多控制。

0
投票

我认为这里的问题是每个表并不是设计创建上下文的方式。
实体框架的设计是(在最一般的情况下),每个表都有一个类来表示该表中的任何行。对于不同的表,预计将定义另一个类。然后,你就得到了你的派生

DbContext

通过为每个表类创建适当的
DbContext
,一个
DbSet
可以为任意多个表提供服务。如果您出于某种原因希望它们在不同的上下文中工作,EF 的设计将期望从
DbContext
派生出一个不同的类,并拥有自己的
DbSet

警告:如果您仅使用相同的 tables 连接到不同的 databases,这意味着列完全对应等,您可以使用相同的
DbContext
,根据需要为构造函数提供不同的连接字符串。


0
投票

我让它与重写 DbContext.OnConfiguring 一起工作:

  protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  {  
     base.OnConfiguring(optionsBuilder);
     optionsBuilder.EnableServiceProviderCaching(false);
  }

我可以通过这种方式解决的情况是这样的:

EF Core 6、XUnit、SQLite 内存、一个测试类、两个顺序运行的测试方法。

在 Visual Studio TestRunner 中一次运行两个测试方法时,仅在第一个测试方法中调用 DbContext.OnModelCreating,而不是在第二个测试方法中调用。

单独或以不同顺序运行测试方法时,效果相同,与先执行哪个测试方法无关。

© www.soinside.com 2019 - 2024. All rights reserved.