【发布时间】:2019-01-24 10:27:29
【问题描述】:
我正在使用域驱动设计在 .Net Core 中开发微服务。基础设施层有 EF Core DbContext 来访问数据库,在我的存储库中,我有异步方法来检索数据。
因为 Include/ThenInclude 不支持过滤(至少不支持 Ef Core 2.1),所以我在谷歌搜索如何替换 Include 时尝试了所有可能的方法。我也观看了有关 Ef Core 的 Pluralsight 视频,当我看到显式加载选项时,我真的很高兴,因为它能够过滤相关对象,但是当我将其中一个方法重写为显式版本时,查询运行了几个毫秒上升到几分钟!
在我的实体配置中,我设置了所有导航和外键,但我不确定显式加载是否需要任何额外设置?在推荐使用全局过滤器之前,请注意 Where 子句通常较长,因此下面的示例只是实际过滤器的简化版本!
这就是我的方法的样子(TransferService 用作聚合,TransferServiceDetail 和任何其他类都只是 TransferService 域中的实体):
public async Task<IEnumerable<TransferService>> GetAllAsync(
TransferServiceFilter transferServiceFilter)
{
int? pageIndex = null;
int? itemsPerPage = null;
IEnumerable<TransferService> filteredList = DBContext.TransferServices.Where(
ts => !ts.IsDeleted); //This one itself is quick.
//This is just our filtering, it does not affect performance.
if (transferServiceFilter != null)
{
pageIndex = transferServiceFilter.PageIndex;
itemsPerPage = transferServiceFilter.ItemsPerPage;
filteredList = filteredList.Where(f =>
(transferServiceFilter.TransferSupplierId == null ||
f.TransferSupplierId == transferServiceFilter.TransferSupplierId) &&
(transferServiceFilter.TransferDestinationId == null ||
f.TransferDestinationId == transferServiceFilter.TransferDestinationId) &&
(transferServiceFilter.TransferSupplierId == null ||
f.TransferSupplierId == transferServiceFilter.TransferSupplierId) &&
(string.IsNullOrEmpty(transferServiceFilter.TransportHubRef) ||
f.NormalizeReference(f.TransportHubRef) ==
f.NormalizeReference(transferServiceFilter.TransportHubRef)));
}
//This is just for paging and again, this is quick.
return await FilterList(filteredList.AsQueryable(), pageIndex, itemsPerPage);
}
public async Task<IEnumerable<TransferService>> GetAllWithServiceDetailsAsync(
TransferServiceFilter transferServiceFilter)
{
IEnumerable<TransferService> returnList = await GetAllAsync(
transferServiceFilter);
//This might be the problem as I need to iterate through my TransferServices
//to be able to load all TransferServiceDetails that belong to each individual
//Service.
foreach (TransferService service in returnList)
{
await DBContext.Entry<TransferService>(service)
.Collection(ts => ts.TransferServiceDetails.Where(
tsd => !tsd.IsDeleted)).LoadAsync();
}
return returnList;
}
在我的存储库中,我还有其他方法,类似地引用以前的 GetAllXY... 方法(TransferServiceDetails 有 Rates,Rates 有 Periods 等...)。
我的想法是在我只需要 TransferService 数据时简单地调用 GetAllAsync(并且仅此方法就闪电般快速),或者当我还需要所选服务的详细信息等时调用 GetAllWithServiceDetailsAsync,但我在这个父级中的位置越低-child 层次结构,执行变得越慢,我说的是几分钟,而不仅仅是额外的几毫秒,或者在最坏的情况下是几秒钟。
所以我的问题又来了:我可能从显式加载所需的实体配置中遗漏了任何其他设置,或者只是我的查询不正确?或者,只有当只有一个 TransferService 作为父项而不是 TransferServices 列表(在我的情况下为 50-100)并且只有几个与子项相关的实体(在我的情况下,我通常有 5- 10 个详细信息,每个详细信息有 2-3 个费率,每个费率正好有 1 个期间,等等...)?
【问题讨论】:
-
谢谢,但正如我在操作中提到的,我不能使用这些过滤器。有时我需要 IsDeleted 字段,有时我不需要。有时我应用了 x、y、z 过滤器,有时只应用了其中的一部分。
标签: domain-driven-design entity-framework-core loading explicit