Skip to content

AndSpecification - The LINQ expression node type 'Invoke' is not supported in LINQ to Entities. #3

Description

@AndresRamos

When combining multiple specifications I get the following error:
"The LINQ expression node type 'Invoke' is not supported in LINQ to Entities."

I get this error even when combining simple specifications like in the follwing example:

In my MVC ViewModel:

public async Task<ActionResult> Index(ContratosIndexViewModel viewModel)
{
    var contratosSpecification = Specification<Contrato>.All;
    
    if (viewModel.TipoRangoFecha != null)
    {
        contratosSpecification = contratosSpecification.And(new FiltrarPorRangoFechaSpecification(viewModel.FechaInicio, viewModel.FechaFin, viewModel.TipoRangoFecha.Value));
    }

    if (viewModel.ClienteId != null)
    {
        contratosSpecification = contratosSpecification.And(new FiltrarPorClienteIdSpecification(viewModel.ClienteId.Value));
    }

    if (viewModel.EmpresaId != null)
    {
        contratosSpecification = contratosSpecification.And(new FiltrarPorEmpresaIdSpecification(viewModel.EmpresaId.Value));
    }

    viewModel.Contratos = await _mediator.Send(new BuscarContratosQuery(User.Identity.GetUserId(), contratosSpecification));

    return View(viewModel);
}

My Sepcifications:

public class FiltrarPorClienteIdSpecification : Specification<Contrato>
{
    private readonly int _clienteId;

    public FiltrarPorClienteIdSpecification(int clienteId)
    {
        _clienteId = clienteId;
    }

    public override Expression<Func<Contrato, bool>> ToExpression()
    {
        return contrato => contrato.ClienteId == _clienteId;
    }
}

public class FiltrarPorEmpresaIdSpecification : Specification<Contrato>
{
    private readonly int _empresaId;

    public FiltrarPorEmpresaIdSpecification(int empresaId)
    {
        _empresaId = empresaId;
    }

    public override Expression<Func<Contrato, bool>> ToExpression()
    {
        return contrato => contrato.EmpresaId == _empresaId;
    }
}

public class FiltrarPorRangoFechaSpecification : Specification<Contrato>
{
    private readonly DateTime _fechaFin;
    private readonly DateTime _fechaInicio;
    private readonly TipoRangoFechaEnum _tipoFechaFiltro;

    public FiltrarPorRangoFechaSpecification(DateTime fechaInicio, DateTime fechaFin, TipoRangoFechaEnum tipoFechaFiltro = TipoRangoFechaEnum.Creado)
    {
        _fechaInicio = fechaInicio;
        _fechaFin = fechaFin;
        _tipoFechaFiltro = tipoFechaFiltro;
    }

    public override Expression<Func<Contrato, bool>> ToExpression()
    {
        switch (_tipoFechaFiltro)
        {
            case TipoRangoFechaEnum.Creado:
                return contrato => DbFunctions.TruncateTime(contrato.FechaCreado) >= DbFunctions.TruncateTime(_fechaInicio) &&
                                   DbFunctions.TruncateTime(contrato.FechaCreado) <= DbFunctions.TruncateTime(_fechaFin);
            case TipoRangoFechaEnum.Liberado:
                return contrato => DbFunctions.TruncateTime(contrato.FechaLiberado) >= DbFunctions.TruncateTime(_fechaInicio) &&
                                   DbFunctions.TruncateTime(contrato.FechaLiberado) <= DbFunctions.TruncateTime(_fechaFin);
            case TipoRangoFechaEnum.Aprobado:
                return contrato => DbFunctions.TruncateTime(contrato.FechaAprobado) >= DbFunctions.TruncateTime(_fechaInicio) &&
                                   DbFunctions.TruncateTime(contrato.FechaAprobado) <= DbFunctions.TruncateTime(_fechaFin);
            case TipoRangoFechaEnum.Cerrado:
                return contrato => DbFunctions.TruncateTime(contrato.FechaCerrado) >= DbFunctions.TruncateTime(_fechaInicio) &&
                                   DbFunctions.TruncateTime(contrato.FechaCerrado) <= DbFunctions.TruncateTime(_fechaFin);
            case TipoRangoFechaEnum.Vencido:
                return contrato => DbFunctions.TruncateTime(contrato.FechaVencido) >= DbFunctions.TruncateTime(_fechaInicio) &&
                                   DbFunctions.TruncateTime(contrato.FechaVencido) <= DbFunctions.TruncateTime(_fechaFin);
            default:
                return contrato => DbFunctions.TruncateTime(contrato.FechaCreado) >= DbFunctions.TruncateTime(_fechaInicio) &&
                                   DbFunctions.TruncateTime(contrato.FechaCreado) <= DbFunctions.TruncateTime(_fechaFin);
        }
    }
}

In My Handler

public class BuscarContratosQueryHandler : IRequestHandler<BuscarContratosQuery, IEnumerable<ContratoDto>>
{
    private readonly ApplicationDbContext _context;
    private readonly IMapper _mapper;

    public BuscarContratosQueryHandler(ApplicationDbContext context, IMapper mapper)
    {
        _context = context;
        _mapper = mapper;
    }

    public async Task<IEnumerable<ContratoDto>> Handle(BuscarContratosQuery request, CancellationToken cancellationToken)
    {
        return await _context.Contratos.AsNoTracking()
            .Include(contrato => contrato.Empresa)
            .Include(contrato => contrato.Plaza)
            .Include(contrato => contrato.Vendedor)
            .Include(contrato => contrato.Cliente)
            .Include(contrato => contrato.Representante)
            .Where(request.ContratosSpecification.ToExpression())
            .OrderByDescending(c => c.FechaCreado)
            .ProjectTo<ContratoDto>(_mapper.ConfigurationProvider)
            .ToListAsync(cancellationToken);
    }
}

StackTrace

   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.NotSupportedTranslator.Translate(ExpressionConverter parent, Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.BinaryTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.BinaryTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
   at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert()
   at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass43_0.<GetResultsAsync>b__1()
   at System.Data.Entity.Core.Objects.ObjectContext.<ExecuteInTransactionAsync>d__156`1.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<ExecuteAsyncImplementation>d__6`1.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Data.Entity.Utilities.TaskExtensions.CultureAwaiter`1.GetResult()
   at System.Data.Entity.Core.Objects.ObjectQuery`1.<GetResultsAsync>d__43.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Data.Entity.Utilities.TaskExtensions.CultureAwaiter`1.GetResult()
   at System.Data.Entity.Internal.LazyAsyncEnumerator`1.<FirstMoveNextAsync>d__9.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Data.Entity.Infrastructure.IDbAsyncEnumerableExtensions.<ForEachAsync>d__2`1.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at SistemaVentasMaquila.Core.Application.Contratos.Queries.BuscarContratos.BuscarContratosQueryHandler.<Handle>d__3.MoveNext() in C:\Users\gerar\Source\Repos\AndresRamos\SistemaVentasMaquila\SistemaVentasMaquila.Core.Application\Contratos\Queries\BuscarContratos\BuscarContratosQueryHandler.cs:line 27
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at SistemaVentasMaquila.Controllers.ContratosController.<Index>d__2.MoveNext() in C:\Users\gerar\Source\Repos\AndresRamos\SistemaVentasMaquila\SistemaVentasMaquila\Controllers\ContratosController.cs:line 90

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions