EF Core 和 Automapper - 过滤子记录

CT1*_*.IT 3 c# entity-framework automapper entity-framework-core .net-core

我想进行一个 EF Core 调用,返回一个父对象以及经过过滤的关联子对象列表,并将其投影到 dto。我想通过 EF Core Linq 查询来执行此操作,我怀疑 ProjectTo 部分忽略了到目前为止的过滤。是否可以?

  • EF 核心 5.0
  • 自动映射器7.0.0

我有另一个查询,它获取父记录并包含所有没有过滤器的子记录,因此如果可能的话,我想在 Dto 映射配置之外实现一些内容。

领域对象

public class ParentThing
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public List<ChildThing> ChildThings { get; set; }
}

public class ChildThing
{
    public Guid Id { get; set; }
    public Guid ParentThingId { get; set; }
    public DateTime Date { get; set; }
    public ParentThing ParentThing { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

托斯

public class ParentThingDto : IMapFrom<ParentThing>
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public List<ChildThingDto> ChildThings { get; set; }
}

public class ChildThingDto : IMapFrom<ChildThing>
{
    public Guid Id { get; set; }
    public DateTime Date { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

询问

var upUntilDate = new DateTime(2013,1,1);

return await _context.ParentThings
  .Where(x => x.Id == request.ParentThingId)
  .Include(x => x.ChildThings.Where(y => y.Date <= upUntilDate))
  .ProjectTo<ParentThingDto>(_mapper.ConfigurationProvider)
  .FirstOrDefaultAsync();
Run Code Online (Sandbox Code Playgroud)

我得到什么

{
  "id": "a5c8f72a-4682-4f62-b231-4c77c0615b84",
  "name": "Parent thing 9",
  "childThings": [
    {
      "id": "ff5fda07-1c15-411c-b72e-e126b91513b3",
      "date": "2014-06-26T22:41:20.7141034"
    },
    {
      "id": "4dded8a3-2231-442e-b40a-1e114da2665a",
      "date": "2012-04-02T06:51:31.963399"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

我期望/想要什么

请注意,我只返回一个孩子的东西,而不是 2 个,这是因为一个孩子有一个日期,之后2013-01-01是我想要的过滤点。

{
  "id": "a5c8f72a-4682-4f62-b231-4c77c0615b84",
  "name": "Parent thing 9",
  "childThings": [
    {
      "id": "4dded8a3-2231-442e-b40a-1e114da2665a",
      "date": "2012-04-02T06:51:31.963399"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

只是注意说IMapFrom<T>仅执行以下操作

public interface IMapFrom<T>
{   
    void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType());
}
Run Code Online (Sandbox Code Playgroud)

joa*_*del 5

当您通过手动或使用 AutoMapper投影到自定义 dto 投影时,据我所知Include不起作用。Select

相反,使用自定义配置文件

public class CustomProfile : Profile
    {
        public CustomProfile()
        {
            DateTime? upUntilDate = null;

            CreateMap<ParentThing, ParentThingDto>()
                .ForMember(m => m.ChildThings, opt => 
                    opt.MapFrom(m => m.ChildThings.Where(y => 
                       upUntilDate.HasValue ? y.Date <= upUntilDate : true))
                    );
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后当您投影时,您将upUntilDate参数添加到ProjectTo

var upUntilDate = new DateTime(2013,1,1);

return await _context.ParentThings
  .Where(x => x.Id == request.ParentThingId)
  .ProjectTo<ParentThingDto>(_mapper.ConfigurationProvider, new { upUntilDate })
  .FirstOrDefaultAsync();
Run Code Online (Sandbox Code Playgroud)

如果您不想过滤子项,只需将 upUntilDate 设置为 null(或不添加参数)。

  • 哇,对于我几个小时以来的同一问题终于有了一个很好的答案。用于在映射器内部进行过滤的自定义字段就是我所需要的。谢谢你! (2认同)