首页 > 解决方案 > LINQ 内部的 MapTo() 返回相同数据的多次迭代

问题描述

我正在使用 .NET Core 和 ASP.NET 样板框架。在我被要求修复的一些代码中,我们有一个GetAll()方法应该从 MsSql 数据库返回一组行。原代码:

public IEnumerable<GuidelineCategoriesDto> GetAll(bool activeFilter = true)
{
    return _guidelineCategoriesRepo.GetAll().Select(x => x.MapTo(new GuidelineCategoriesDto())).ToList();
}

我在使用这种方法时遇到的问题是它会返回数据库中尚未软删除的最新行。但是,它将返回同一行的次数等于该表中未删除行的数量。所以基本上我会取回一个IEnumerable包含所有重复项的内容。为了解决这个问题,我将此方法更改为以下。

public IEnumerable<GuidelineCategoriesDto> GetAll(bool activeFilter = true)
{
    // return _guidelineCategoriesRepo.GetAll().Select(x => ObjectMapper.Map<GuidelineCategoriesDto>(x)).ToList();
    return ObjectMapper.Map<IEnumerable<GuidelineCategoriesDto>>(_guidelineCategoriesRepo.GetAll());
}

这(包括注释行)解决了我的所有问题并返回了正确的数据。我的问题是为什么我提到的第一种方法会以它的方式起作用。我不熟悉MapTo我习惯使用的方法ObjectMapper,但从我发现的情况来看,我仍然无法确定它为什么会这样。

我的 DTO 具有正确的AutoMap数据注释,并且DbSet在 中DbContext,如果有的话。

标签: linqasp.net-coreentity-framework-coreautomapperaspnetboilerplate

解决方案


这个...

_guidelineCategoriesRepo.GetAll().Select(x => x.MapTo(new GuidelineCategoriesDto())).ToList();

...实际上是:

var dto = new GuidelineCategoriesDto();
_guidelineCategoriesRepo.GetAll().Select(x => x.MapTo(dto)).ToList();

换句话说,您将每个实体映射到同一个 DTO。

由于最后一个实体是最后映射的,这意味着从每个实体映射的 DTO 似乎是从最后一个实体映射的 DTO 的副本。但实际上是一个 DTO 多次出现。

这会起作用:

_guidelineCategoriesRepo.GetAll().Select(x => x.MapTo<GuidelineCategoriesDto>()).ToList();

避免MapTo;利用ObjectMapper

https://aspnetboilerplate.com/Pages/Documents/Object-To-Object-Mapping#mapto-extension-methods

由于MapTo扩展方法是static,它们使用 AutoMapper 的静态实例 ( Mapper.Instance)。这对于应用程序代码来说既简单又好,但是在单元测试中可能会遇到问题,因为静态配置和映射器在不同的测试之间共享,所有这些都相互影响。


推荐阅读