构建 Entity Framework Core 查询的最佳方法

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

我正在构建一个从 Telegram 获取数据的 .NET 应用程序。我将 Telegram 频道、主题和消息存储在 SQLite 数据库中。数据库的结构如下所示:

enter image description here

基本上:

  • 频道可以有或不能有很多主题
  • 频道可以有很多消息
  • 主题可以有很多消息

我希望能够正确检索频道、主题和消息,这样当我从 Telegram 同步时,我就不会插入重复项。我有几个测试通道,其中有 100 个主题和 10000 条消息,正如人们所期望的那样,像这样的 LINQ 调用非常糟糕

var channels = teleContext.Channels
                          .Include(a => a.Messages)
                          .Include(a => a.Topics).ToList();

即使我向该查询添加

Where
,它也很慢(例如
where ChannelID == someVariable
)。我需要能够更新频道中的大多数列、主题中的一些列以及消息中的几乎所有列(以确保 Telegram 的数据准确)。

是否可以实现急切加载和拆分查询的组合,以使对数据库的调用性能更好?

sqlite .net-core entity-framework-core
1个回答
0
投票

AsSplitQuery()
将有助于减少大型连接集的笛卡尔积,但在检测重复项时要附加数千个或更多子记录的情况下,您可能需要在以下方面发挥创意:如何比较条目。

如果您想要插入给定频道的 10 条消息(如果它们尚未随频道更新一起存在),那么我会考虑拆分操作,而不是加载频道和所有消息。您可以单独加载通道,更新该通道,然后在插入 10 个新行中的一行或多行之前查询与该通道相关的消息是否有重复项。 例如,如果消息具有发布日期和一些其他属性,您可以将其用作第一遍来识别可能的重复项:

var startDateTime = newMessages.Min(x => x.MessageDateTime);
var endDateTime = newMessages.Max(x => x.MessageDateTime);

var channel = await context.Channels.SingleAsync(x => x.Id == channelId);
var existingMessages = await context.Messages
    .Where(x => x.Channel.Id == channelId
        && x.MessageDateTime >= startDateTime && x.MessageDateTime <= endDateTime)
    .ToListAsync();

从这里您可以更仔细地查看一系列消息,以查找要更新或插入的重复项或条目。

您还可以选择在 EF Core 中进行选择性预加载:

var channel = await context.Channels
    .Include(x => x.Messages
        .Where(m => m.MessageDateTime >= startDateTime && m.MessageDateTime <= endDateTime))
    .AsSplitQuery()
    .SingleAsync(x => x.Id == channelId)

将检索的数据限制在子集范围内以执行相关比较,无论是按日期范围还是特定标识列。尽你所能减少要比较的集合。

由于我们正在读取并可能修改大量行,如果您按 Channel 将其分解,那么我建议使用 DbContextFactory 来绑定每次迭代的新 DbContext,或者在通道之间调用 context.ChangeTracker.Clear() 来刷新更改跟踪缓存。如果我们最终在每个通道中加载数百条消息(数万条),那么当我们将更多消息等添加到跟踪缓存中时,性能将逐渐变慢,因为每个查询都会在缓存中进行筛选,寻找潜在的相关引用来链接。

如果您需要同步较大的数据集,那么您可能会考虑将比较数据集批量插入临时表中,然后使用插入的数据集与当前数据之间的联接进行查询,而不是将整个通道(或多个通道)加载到内存中来执行比较。如果此过程是由用户操作启动的,那么我还会考虑将其移交给队列,其中后台作业会拾取队列请求,在作业完成时处理并更新作业的状态,并成功或失败以及任何相关的信息。结果提供给用户。如果多个用户同时触发这些相当繁重的请求,这还可以帮助防止系统陷入困境。

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