Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

968
Visualizações
C# Linq: Combine múltiples .Where() con una cláusula *OR*

He estado buscando mucho sobre mi problema actual, pero no pude encontrar una respuesta real para resolver ese problema.

Estoy tratando de crear una consulta LINQ que produzca el siguiente SQL:

 SELECT * FROM TABLE WHERE (Field1 = X, Field2 = Y ... ) or (Field3 = Z)

En una situación normal, simplemente haría esto:

 Object.Where(c => (c.Field1 == X && c.Field2 == Y) || (c.Field3 == Z))

No puedo usar este enfoque porque la consulta se crea usando varias llamadas .Where() .

Teniendo un ejemplo:

 // This is a short example, the real world situation has 20 fields to check and they are all connected with an AND. if (model.Field1.HasValue) { Query = Query.Where(c => c.Field1 == X) } if (model.Field2.HasValue) { Query = Query.Where(c => c.Field2 == X) } [...] like 20 more of these .Where() calls.

y así es como se me complica. Todas estas llamadas .Where() están creando una consulta Linq que está conectada con AND , lo cual está bien.

¿Cómo les permito ejecutar con paréntesis y agregar un OR simple ahora usando la API?

¿Hay alguna manera de guardar el predicado en algunas variables para poder hacer algo como:

 Query = Query.Where(c => previousPredicates || c.Field3 == X)

o como solucionar ese problema?

Creo que debe haber una buena solución para ese problema en particular y no soy el único que la necesita, pero no estoy absolutamente seguro de cómo lograrlo.

PD: Realmente no puedo eliminar las múltiples .Where() y escribir SQL directo no es una opción.

EDITAR StackOverflow quiere que diga por qué mi pregunta es diferente de las demás. Bueno, la cosa va de Parentheses . No quiero conectar todos los .Where() con una sola cláusula OR, quiero dejarlos con AND y agregar otra cláusula OR mientras todas las consultas AND están entre paréntesis.

over 4 years ago · Santiago Trujillo
4 Respostas
Responde à pergunta

0

Primero, cree algunos métodos auxiliares de extensión para combinar más fácilmente dos predicados Func<T,bool> :

 public static Func<T, bool> And<T>(this Func<T, bool> left, Func<T, bool> right) => a => left(a) && right(a); public static Func<T, bool> Or<T>(this Func<T, bool> left, Func<T, bool> right) => a => left(a) || right(a);

Luego puedes usarlos para encadenar predicados:

 var list = Enumerable.Range(1, 100); Func<int, bool> predicate = v => true; // start with true since we chain ANDs first predicate = predicate.And(v => v % 2 == 0); // numbers dividable by 2 predicate = predicate.And(v => v % 3 == 0); // numbers dividable by 3 predicate = predicate.Or(v => v % 31 == 0); // numbers dividable by 31 var result = list.Where(predicate); foreach (var i in result) Console.WriteLine(i);

Producción:

 6 12 18 24 30 31 36 42 48 54 60 62 66 72 78 84 90 93 96
over 4 years ago · Santiago Trujillo Relatório

0

Puede usar Expression para crear en un solo paso como este:

 Expression<Func<Model, bool>> exp = (model => ((model.Field1.HasValue && c.Field1 == X) && (model.Field2.HasValue && c.Field2 == X)) || model.Field3 == X )

Una vez que haya definido sus predicados, es muy fácil usarlos en una consulta.

 var result = Query.AsQueryable().Where(exp)

Verifique el código en esta esencia: mi url esencial

ACTUALIZACIÓN 1: si tiene que usar pasos para crear su expresión, puede usar esto:

 Expression<Func<Model, bool>> exp = c => true; if (model.Field1.HasValue) { var prefix = exp.Compile(); exp = c => prefix(c) && c.Field1 == X; } if (model.Field2.HasValue) { var prefix = exp.Compile(); exp = c => prefix(c) && c.Field2 == X; } [...] like 20 more of these .Where() calls.
over 4 years ago · Santiago Trujillo Relatório

0

Si desea crear su consulta mediante programación y hacer que se ejecute en su servidor SQL en lugar de obtener todos los registros y consultar en la memoria, debe usar el conjunto de métodos estáticos en la clase Expression y crear su consulta con ellos. En tu ejemplo:

 public class Query // this will contain your 20 fields you want to check against { public int? Field1; public int? Field2; public int? Field3; public int Field4; } public class QueriedObject // this is the object representing the database table you're querying { public int QueriedField; } public class Program { public static void Main() { var queryable = new List<QueriedObject>().AsQueryable(); var query = new Query { Field2 = 1, Field3 = 4, Field4 = 2 }; // this represents the argument to your lambda expression var parameter = Expression.Parameter(typeof(QueriedObject), "qo"); // this is the "qo.QueriedField" part of the resulting expression - we'll use it several times later var memberAccess = Expression.Field(parameter, "QueriedField"); // start with a 1 == 1 comparison for easier building - // you can just add further &&s to it without checking if it's the first in the chain var expr = Expression.Equal(Expression.Constant(1), Expression.Constant(1)); // doesn't trigger, so you still have 1 == 1 if (query.Field1.HasValue) { expr = Expression.AndAlso(expr, Expression.Equal(memberAccess, Expression.Constant(query.Field1.Value))); } // 1 == 1 && qo.QueriedField == 1 if (query.Field2.HasValue) { expr = Expression.AndAlso(expr, Expression.Equal(memberAccess, Expression.Constant(query.Field2.Value))); } // 1 == 1 && qo.QueriedField == 1 && qo.QueriedField == 4 if (query.Field3.HasValue) { expr = Expression.AndAlso(expr, Expression.Equal(memberAccess, Expression.Constant(query.Field3.Value))); } // (1 == 1 && qo.QueriedField == 1 && qo.QueriedField == 4) || qo.QueriedField == 2 expr = Expression.OrElse(expr, Expression.Equal(memberAccess, Expression.Constant(query.Field4))); // now, we combine the lambda body with the parameter to create a lambda expression, which can be cast to Expression<Func<X, bool>> var lambda = (Expression<Func<QueriedObject, bool>>) Expression.Lambda(expr, parameter); // you can now do this, and the Where will be translated to an SQL query just as if you've written the expression manually var result = queryable.Where(lambda); } }
over 4 years ago · Santiago Trujillo Relatório

0

Ok, has tenido tu propia respuesta sobre linq.

Permítanme presentarles un enfoque diferente usando Dynamic.linq

 // You could build a Where string that can be converted to linq. // and do if sats and append your where sats string. as the example below var query = "c => (c.Field1 == \" a \" && c.Field2 == Y) || (c.Field3 == \" b \")"; var indicator = query.Split('.').First(); // the indicator eg c // assume TABLE is the name of the class var p = Expression.Parameter(typeof(TABLE), indicator); var e = DynamicExpression.ParseLambda(new[] { p }, null, query); // and simple execute the expression var items = Object.Where(e);
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda