问题
I am using .NET Core with the ASP.NET Boilerplate framework. In some code that I was given to fix, we had a GetAll()
method that was supposed to return a collection of rows from the MsSql database. The original code:
public IEnumerable<GuidelineCategoriesDto> GetAll(bool activeFilter = true)
{
return _guidelineCategoriesRepo.GetAll().Select(x => x.MapTo(new GuidelineCategoriesDto())).ToList();
}
The problem I was running into with this method, is that it would return the latest row that had not been soft-deleted in the database. However, it would return that same row a number of times equal to the amount of non-deleted rows in that table. So essentially I would get back an IEnumerable
that contained all duplicates. To fix this, I changed this method to the following.
public IEnumerable<GuidelineCategoriesDto> GetAll(bool activeFilter = true)
{
// return _guidelineCategoriesRepo.GetAll().Select(x => ObjectMapper.Map<GuidelineCategoriesDto>(x)).ToList();
return ObjectMapper.Map<IEnumerable<GuidelineCategoriesDto>>(_guidelineCategoriesRepo.GetAll());
}
This (including the commented line) fixed all my issues and returned the correct data. My question is why the first method I mentioned acted in the way that it did. I am not familiar with the MapTo
method as I'm used to using ObjectMapper
, but from what I found about it I still cannot determine why it behaved in the way that it did.
My DTO has the correct AutoMap
data annotation and the DbSet
is in the DbContext
, if any of that matters.
回答1:
This...
_guidelineCategoriesRepo.GetAll().Select(x => x.MapTo(new GuidelineCategoriesDto())).ToList();
...is effectively:
var dto = new GuidelineCategoriesDto();
_guidelineCategoriesRepo.GetAll().Select(x => x.MapTo(dto)).ToList();
In other words, you are mapping every entity to the same DTO.
Since the last entity is mapped last, this means that the DTO mapped from every entity appears to be a duplicate of the DTO mapped from the last entity. But is actually one DTO appearing multiple times.
This would work:
_guidelineCategoriesRepo.GetAll().Select(x => x.MapTo<GuidelineCategoriesDto>()).ToList();
Avoid MapTo
; use ObjectMapper
From https://aspnetboilerplate.com/Pages/Documents/Object-To-Object-Mapping#mapto-extension-methods:
Since the
MapTo
extension methods arestatic
, they use AutoMapper's static instance (Mapper.Instance
). This is simple and fine for the application code, but you can have problems in unit tests since the static configuration and mapper is shared among different tests, all effecting each other.
来源:https://stackoverflow.com/questions/55145922/mapto-inside-of-linq-returning-multiple-iterations-of-same-data