我有多个相同但内容不同的 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]
*如果任何代码看起来错误,我会重命名一些变量,因为它们对业务敏感。
OnModelCreating
只会被调用一次,这是默认行为。
根据OnModelCreating文档。
通常,仅在创建派生上下文的第一个实例时调用此方法一次。然后,该上下文的模型将被缓存,并且适用于应用程序域中该上下文的所有其他实例。可以通过在给定 ModelBuidler 上设置 ModelCaching 属性来禁用此缓存,但请注意,这会严重降低性能。通过直接使用 DbModelBuilder 和 DbContextFactory 类提供对缓存的更多控制。
我认为这里的问题是每个表并不是设计创建上下文的方式。
实体框架的设计是(在最一般的情况下),每个表都有一个类来表示该表中的任何行。对于不同的表,预计将定义另一个类。然后,你就得到了你的派生
DbContext
。 DbContext
,一个 DbSet
可以为任意多个表提供服务。如果您出于某种原因希望它们在不同的上下文中工作,EF 的设计将期望从 DbContext
派生出一个不同的类,并拥有自己的 DbSet
。
DbContext
,根据需要为构造函数提供不同的连接字符串。
我让它与重写 DbContext.OnConfiguring 一起工作:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.EnableServiceProviderCaching(false);
}
我可以通过这种方式解决的情况是这样的:
EF Core 6、XUnit、SQLite 内存、一个测试类、两个顺序运行的测试方法。
在 Visual Studio TestRunner 中一次运行两个测试方法时,仅在第一个测试方法中调用 DbContext.OnModelCreating,而不是在第二个测试方法中调用。
单独或以不同顺序运行测试方法时,效果相同,与先执行哪个测试方法无关。