AndSpecification - The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
AndresRamos opened this issue · comments
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