Home > database >  I want to use Sieve and DTOs in the same project
I want to use Sieve and DTOs in the same project

Time:07-09

I want to use Sieve in my Web API project. I am using Data Transfer Objects (Dtos) instead of directly sending out my database entity models over the API. I am using Automapper to quickly map the db model objects to the Dtos. A sample API endpoint:

   [HttpGet]
   public async Task<ActionResult<IEnumerable<RdtoSetup>>> GetSetups([FromQuery] SieveModel sieveModel)
   {
      if (_context.Setups == null)
      {
         return NotFound();
      }
      var setups = _context.Setups.AsNoTracking();
      var results = _mapper.Map<IEnumerable<RdtoSetup>>(await setups.ToListAsync());
      var filtered = _sieveProcessor.Apply(sieveModel, results);
      return Ok(filtered);
   }

As you can see from the code, I am unable to leverage the database for filtering sorting etc. I have to load all the results into an IEnumerable<RdtoSetup> before I can apply the Sieve model for filtering.

What am I doing wrong? Is there a way to get the benefit of Sieve without having to load complete tables from db into memory?


Solution from @Steve-py

Updated code that still uses my Automapper profile:

[HttpGet]
public async Task<ActionResult<IEnumerable<RdtoSetup>>> GetSetups([FromQuery] SieveModel sieveModel)
{
    if (_context.Setups == null)
    {
        return NotFound();
    }
    var setups = _context.Setups.AsQueryable();
    var results = _mapper.ProjectTo<RdtoSetup>(setups);
    var filtered = _sieveProcessor.Apply(sieveModel, results);
    return Ok(await filtered.ToListAsync());
}

CodePudding user response:

When working with Automapper and EF, you should leverage Automapper's ProjectTo rather than Map. This will keep the mapping operation within the IQueryable so that the results don't need to be materialized and the Sieve operation should flow down to the query. Using ProjectTo you also don't need to worry about AsNoTracking or eager loading relationships with Include:

var results = _context.Setups.ProjectTo<RdtoSetup>(mapperConfiguration);
var filtered = await _sieveProcessor.Apply(sieveModel, results).ToListAsync();

Where mapperConfiguration is an Automapper Config for converting from your Entity(ies) to DTO(s).

I haven't worked with Sieve before for sorting models, but if that doesn't translate through ProjectTo, then the alternative would be to derive your Sieve Model off the Entity rather than the DTO and do the mapper.Map last:

var setups = _context.Setups.AsNoTracking();
var filtered = _sieveProcessor.Apply(sieveModel, setups);
var results = _mapper.Map<IEnumerable<RdtoSetup>>(await filtered.ToListAsync());

return Ok(results);
  • Related