.net - query - Cláusula dynamic where en LINQ-con nombres de columna disponibles en tiempo de ejecución
query dynamic object c# (4)
Puede activar y desactivar sus cláusulas where usando algunas expresiones lógicas.
//Turn on all where clauses
bool ignoreFirstName = false;
bool ignoreLastName = false;;
bool ignoreAddress = false;
//Decide which WHERE clauses we are going to turn off because of something.
if(something)
ignoreFirstName = true;
//Create the query
var queryCustomers = from c in db.Customers
where (ignoreFirstName || (c.ContactFirstName.Contains("BlackListed")))
where (ignoreLastName || (c.ContactLastName.Contains("BlackListed")))
where (ignoreAddress || (c.Address.Contains("BlackListed"))
select j;
Si ignoreFirstName es verdadero en la consulta, se ignorará la condición en el otro lado de la declaración o.
Descargo de responsabilidad: He resuelto el problema utilizando expresiones de System.Linq.Expressions, pero sigo buscando una forma mejor / más fácil.
Considera la siguiente situación:
var query =
from c in db.Customers
where (c.ContactFirstName.Contains("BlackListed") ||
c.ContactLastName.Contains("BlackListed") ||
c.Address.Contains("BlackListed"))
select c;
Las columnas / atributos que deben verificarse contra el término en la lista negra solo están disponibles para mí en tiempo de ejecución. ¿Cómo puedo generar esta cláusula dynamic where?
Una complicación adicional es que la colección Queryable (db.Customers más arriba) se escribe en un Queryable de la clase base de ''Customer'' (diga ''Person'') y, por lo tanto, escribir c.Address como se indica anteriormente no es una opción.
@Geoff tiene la mejor opción, solo Dynamic LINQ.
Si desea ir a la forma de generar consultas en tiempo de ejecución utilizando Lambda, le recomiendo que use PredicateBuilder ( http://www.albahari.com/nutshell/predicatebuilder.aspx ) y tenga algo como esto:
Expression<Fun<T,bool>> pred = null; //delcare the predicate to start with. Note - I don''t know your type so I just used T
if(blacklistFirstName){
pred = p => p.ContactFirstName.Contains("Blacklisted");
}
if(blacklistLastName){
if(pred == null){
pred = p => p.ContactLastName.Contains("Blacklisted"); //if it doesn''t exist just assign it
}else{
pred = pred.And(p => p.ContactLastName.Contains("Blacklisted"); //otherwise we add it as an And clause
}
}
Y así sucesivamente para todas las columnas que desea incluir. Cuando llegas a tu consulta solo necesitas algo como esto:
var results = db.Customers.Where(pred).Select(c => c);
He usado esto para construir LINQ para buscar donde hay unas 20 opciones diferentes y produce un SQL realmente bueno.
Como esto no es LINQ to Objects, sino más bien LINQ to SQL, no tiene otra alternativa además de usar Expressions o un procedimiento almacenado.
var query = from C in db.Customers select c;
if (seachFirstName)
query = query.Where(c=>c.ContactFirstname.Contains("Blacklisted"));
if (seachLastName)
query = query.Where(c=>c.ContactLastname.Contains("Blacklisted"));
if (seachAddress)
query = query.Where(c=>c.Address.Contains("Blacklisted"));
Tenga en cuenta que no son mutuamente excluyentes.