ardalis / Specification

Base class with tests for adding specifications to a DDD model
MIT License
1.95k stars 245 forks source link

Issue about PostProcessingAction #411

Open lumoslnt opened 3 weeks ago

lumoslnt commented 3 weeks ago

I am trying to use PostProcessingAction to filter queries created within the last year, but it doesn't seems to be working, I got the full queries, here is my code:

Query.PostProcessingAction(items => items.Where(e =>
{
    return e.CreatedTime != null && DateTime.TryParse(e.CreatedTime, out var parsedTime) ? parsedTime >= DateTime.Now.AddYears(-1) : false;
}));

I have done some tests, if I return false directly, I will get an empty list, which is expected:

Query.PostProcessingAction(items => items.Where(e =>{ return false; }));

But if I return e.CreatedTime == null, which always be false, I will get the full list:

Query.PostProcessingAction(items => items.Where(e =>{ return e.CreatedTime == null; }));

What is the problem? Am I using it incorrectly?

fiseni commented 3 weeks ago

Hey @lumoslnt

I can not reproduce the issue. Here I created a full sample app. Please reproduce the issue in this sample.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Ardalis.Specification.EntityFrameworkCore" Version="8.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.10" />
  </ItemGroup>

</Project>
using Ardalis.Specification;
using Ardalis.Specification.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

await AppDbContext.SeedAsync();

using var context = new AppDbContext();
var repo = new Repository<Customer>(context);

var result = await repo.ListAsync(new CustomerSpec());

Console.WriteLine(result.Count);

public class CustomerSpec : Specification<Customer>
{
    public CustomerSpec()
    {
        Query.PostProcessingAction(item => item.Where(x => x.CreatedTime == null));
    }
}
public class Repository<T>(AppDbContext context) : RepositoryBase<T>(context) where T : class
{
}
public record Customer
{
    public int Id { get; set; }
    public DateTime? CreatedTime { get; set; }
}

public class AppDbContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=SpecIssue411Db;Trusted_Connection=True");
    }

    public static async Task SeedAsync()
    {
        using var context = new AppDbContext();
        await context.Database.EnsureDeletedAsync();
        await context.Database.EnsureCreatedAsync();
        var customer = new Customer { CreatedTime = DateTime.Now };
        context.Customers.Add(customer);
        await context.SaveChangesAsync();
    }
}