我可以从一个 DbContextFactory、两个 DbContext 执行,每个都有自己的查询吗

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

我不是在这里谈论多个不同的定义上下文。我有一个定义的 DbContext。

当我需要访问数据库时,我有一个

IDbContextFactory<MyDataDbContext>
,用于创建 MyDataDbContext。然后我使用该 DbContext 来访问数据库。

我还知道实例化的DbContext一次只能处理一个查询。它不是线程安全的。所以我并不是在询问在两个任务中使用单个实例化的 DbContext。

这是为了将 DbContext 设置为关闭跟踪。

我的问题是,从那首单曲

IDbContextFactory
中,我可以:

  1. 创建两个(或更多)
    DbContext
    对象。
  2. 同时拨打
    dbContext.TableName.ToListAsync()
  3. 保存 listTasks 中每个任务的返回值。
  4. 致电
    await Task.WaitAll(listTasks);

如果我做到了这一切,会赢吗? Azure SQL 数据库会更快吗?或者它只是将所有请求放入队列中并在开始下一个请求之前启动/完成一个请求?从根本上说,所有这些下面都有一个磁盘驱动器,因此磁盘访问必须排队。但在磁盘 I/O 之前/之后有所有处理。还有处理之前/之后的实体框架。

或者如果我走这条路,我只是给自己找麻烦吗?

我的生产系统是普通的 Azure Web 服务器和 Azure SQL 数据库。

sql-server entity-framework-core azure-sql-database
1个回答
0
投票

使用单独的 DbContext 实例并行化任务很好,只要这些任务可以完全独立运行。但是,您仍然需要考虑诸如数据库锁定之类的细节。如果您有基于代码的处理时间,并行化会有所帮助,但如果大量时间花费在获取/更新数据上,您可能最好首先寻找尽可能高效地完成此操作的方法。与执行 SQL 语句相比,EF 并不是批处理类型操作的最佳选择(如果有这样的选项的话)。首先看看在没有 EF 的情况下如何做到这一点,然后考虑 EF 是否能改进任何东西。

如上述评论中所述,另一个选项是使用 EF Core 7+ 中提供的

ExecuteUpdate()
方法。但请注意,此方法仅针对数据库执行,不会更新可能已加载的跟踪实例。例如:

var record = context.MyTables.Single(x => x.Id == tableId);
// ...
context.MyTables
    .Where(x => x.CategoryId == categoryId)
    .ExecuteUpdate(x => x.SetProperty(t => t.Value, t.Value + 1);
var records = context.MyTables
    .Where(x => x.CategoryId == categoryId)
    .ToList();

如果第一个读取的记录属于相关类别,则最后加载的记录仍将具有原始跟踪实例中未更改的值。该实体的数据库行将已更新,但 EF 不会将更改应用于内存中的跟踪实例。如果使用注入的

ExecuteUpdate
实例中的
DbContext
,那么您可能需要警惕任何跟踪的引用。这可能涉及在任何
context.ChangeTracker.Clear()
调用之前调用
ExecuteUpdate()
,或者确保之后的任何读取都使用
AsNoTracking()
来确保当前数据状态来自数据库。

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