Estamos trabajando en un Visor de registro. El uso tendrá la opción de filtrar por usuario, gravedad, etc. En los días Sql, agregaría a la cadena de consulta, pero quiero hacerlo con Linq. ¿Cómo puedo agregar condicionalmente cláusulas where?Consultas de Linq condicional
Respuesta
si quieres sólo para filtrar si se superan ciertos criterios, hacer algo como esto
var logs = from log in context.Logs
select log;
if (filterBySeverity)
logs = logs.Where(p => p.Severity == severity);
if (filterByUser)
logs = logs.Where(p => p.User == user);
Si lo hace, de esta manera permitirá que su árbol de expresión sea exactamente lo que quiere. De esta forma, el SQL creado será exactamente lo que necesita y nada menos.
sólo tiene que utilizar C# 's & & operador:
var items = dc.Users.Where(l => l.Date == DateTime.Today && l.Severity == "Critical")
Editar: Ah, necesita leer con más cuidado. Quería saber cómo condicionalmente agregar cláusulas adicionales. En ese caso, no tengo idea. :) Lo que probablemente haría es solo preparar varias consultas y ejecutar la correcta, dependiendo de lo que terminé necesitando.
Se podría utilizar un método externo:
var results =
from rec in GetSomeRecs()
where ConditionalCheck(rec)
select rec;
...
bool ConditionalCheck(typeofRec input) {
...
}
Esto funcionaría, pero no puede ser desglosado en los árboles de expresión, lo que significa LINQ a SQL sería ejecutar el código de verificación contra todos los registros.
alternativa:
var results =
from rec in GetSomeRecs()
where
(!filterBySeverity || rec.Severity == severity) &&
(!filterByUser|| rec.User == user)
select rec;
que podrían funcionar en los árboles de expresión, es decir, LINQ to SQL se optimizaría.
Bueno, lo que me pareció que podría poner las condiciones de filtro en una lista genérica de predicados:
var list = new List<string> { "me", "you", "meyou", "mow" };
var predicates = new List<Predicate<string>>();
predicates.Add(i => i.Contains("me"));
predicates.Add(i => i.EndsWith("w"));
var results = new List<string>();
foreach (var p in predicates)
results.AddRange(from i in list where p.Invoke(i) select i);
que se traduce en una lista que contiene "yo", "meyou", y "cortar".
Puede optimizar esto haciendo foreach con los predicados en una función totalmente diferente que Rs todos los predicados.
No es lo más bonito, pero puede usar una expresión lambda y aprobar sus condiciones de manera opcional. En TSQL hago un montón de estos procedimientos para realizar parámetros opcionales:
donde el campo = O @FieldVar @FieldVar IS NULL
Usted podría duplicar el mismo estilo con una la siguiente lambda (un ejemplo de comprobación de autenticación):
MyDataContext db = new MyDataContext();
RunQuery vacío (param1, string param2, int? Param3) {
Func CheckUser = user =>
((param1.Length> 0)? Usuario.Param1 == param1: 1 == 1) & &
((param2.Length> 0) == user.Param2 param2: 1 == 1) & &
(! (Param3 = null) ? user.Param3 == param3: 1 == 1);
Usuario foundUser = db.Users.SingleOrDefault (checkUser);
}
Cuando se trata de LINQ condicional, me gusta mucho del patrón de filtros y tuberías.
http://blog.wekeroad.com/mvc-storefront/mvcstore-part-3/
Básicamente, usted crea un método de extensión para cada caso de filtro que toma IQueryable y un parámetro.
public static IQueryable<Type> HasID(this IQueryable<Type> query, long? id)
{
return id.HasValue ? query.Where(o => i.ID.Equals(id.Value)) : query;
}
Otra opción sería utilizar algo así como el PredicateBuilder discutió here. Se le permite escribir código como el siguiente:
var newKids = Product.ContainsInDescription ("BlackBerry", "iPhone");
var classics = Product.ContainsInDescription ("Nokia", "Ericsson")
.And (Product.IsSelling());
var query = from p in Data.Products.Where (newKids.Or (classics))
select p;
Tenga en cuenta que sólo tengo que esto funcione con Linq 2 SQL. EntityFramework no implementa Expression.Invoke, que se requiere para que este método funcione. Tengo una pregunta con respecto a este problema here.
Este es un gran método para quienes usan una capa lógica de negocios en la parte superior de su repositorio junto con una herramienta como AutoMapper para correlacionar entre transferencia de datos objetos y modelos de Entidad. El uso del generador de predicados le permitirá modificar dinámicamente su IQueryable antes de enviarlo a AutoMapper para acoplarlo, es decir, llevar la lista a la memoria. Tenga en cuenta que también es compatible con Entity Framework. – chrisjsherm
Tuve un requisito similar recientemente y finalmente encontré esto en MSDN. CSharp Samples for Visual Studio 2008
Las clases incluidas en la muestra DynamicQuery de la descarga le permiten crear consultas dinámicas en tiempo de ejecución en el siguiente formato:
var query =
db.Customers.
Where("City = @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("new(CompanyName as Name, Phone)");
El uso de este se puede construir una cadena de consulta dinámicamente en tiempo de ejecución y pasarlo en el método en el que():
string dynamicQueryString = "City = \"London\" and Order.Count >= 10";
var q = from c in db.Customers.Where(queryString, null)
orderby c.CompanyName
select c;
terminé usando una respuesta similar a Daren de, pero con una interfaz IQueryable:
IQueryable<Log> matches = m_Locator.Logs;
// Users filter
if (usersFilter)
matches = matches.Where(l => l.UserName == comboBoxUsers.Text);
// Severity filter
if (severityFilter)
matches = matches.Where(l => l.Severity == comboBoxSeverity.Text);
Logs = (from log in matches
orderby log.EventTime descending
select log).ToList();
Eso genera la consulta antes de llegar a la base de datos. El comando no se ejecutará hasta que aparezca .ToList() al final.
Si necesita filtrar la base en una lista/Matriz utilizar lo siguiente:
public List<Data> GetData(List<string> Numbers, List<string> Letters)
{
if (Numbers == null)
Numbers = new List<string>();
if (Letters == null)
Letters = new List<string>();
var q = from d in database.table
where (Numbers.Count == 0 || Numbers.Contains(d.Number))
where (Letters.Count == 0 || Letters.Contains(d.Letter))
select new Data
{
Number = d.Number,
Letter = d.Letter,
};
return q.ToList();
}
Esta es de lejos la mejor y más correcta respuesta. El condicional || solo compara la primera parte y se salta la segunda si la primera parte es verdadera ... ¡bien hecho! –
Este constructo incluye la parte 'o' de la expresión en la consulta SQL generada. La respuesta aceptada generará declaraciones más eficientes. Dependiendo de las optimizaciones del proveedor de datos, por supuesto. LINQ-to-SQL puede tener una mejor optimización, pero LINQ-to-Entities no. – Suncat2000
Hacer esto:
bool lastNameSearch = true/false; // depending if they want to search by last name,
tener esto en la declaración where
:
where (lastNameSearch && name.LastNameSearch == "smith")
significa que cuando se crea la consulta final, si lastNameSearch
es false
la consulta omitirá por completo cualquier SQL para la búsqueda del apellido.
Depende del proveedor de datos. LINQ-to-Entities no lo optimiza tan bien. – Suncat2000
- 1. LINQ condicional cláusula Where
- 2. Depuración de consultas LINQ
- 3. condicional en LINQ DONDE
- 4. LINQ Grupo condicional
- 5. Compilar automáticamente consultas de Linq
- 6. múltiplo de Linq donde consultas
- 7. Extensión de consultas LINQ para
- 8. LINQ y la suma condicional
- 9. Cómo escribir consultas asincrónicas LINQ?
- 10. LINQ consultas con 3 niveles
- 11. C# LINQ consultas - Agrupar por
- 12. LINQ a las consultas XML
- 13. Optimizar consultas LINQ-to-SQL
- 14. Orden de clasificación "orderby" condicional en LINQ
- 15. NHibernate 3 Caché de consultas Linq
- 16. Tus consultas favoritas de LINQ-to-Objects
- 17. Prueba de Moq LINQ Donde consultas
- 18. Consultas de LINQ en listas posiblemente infinitas
- 19. Consultas de LINQ frente a Procedimientos almacenados
- 20. Método de refactorización que contiene consultas LINQ
- 21. lista de consultas LINQ contiene una lista
- 22. condicional incluir en linq a las entidades?
- 23. ¿LINQ-to-SQL admite consultas compostables?
- 24. Comprobando automáticamente relaciones NULL con consultas LINQ
- 25. Cómo cargar consultas Múltiples a muchas LINQ?
- 26. consultas linq anidadas, ¿cómo obtener valores distintos?
- 27. problema de caché de nhibernate con consultas de linq
- 28. LINQ para consultas LIKE de elementos de matriz
- 29. ¿Podría abstraer sus consultas LINQ en los métodos de extensión
- 30. ¿Es posible manejar excepciones dentro de consultas LINQ?
Hola ¿Tiene alguna sugerencia para hacer las cláusulas where ORs en lugar de ANDs ..? –
Sí ... es un poco difícil de hacer. Lo mejor que he visto es a través del patrón de especificación y tirando del predicado dentro de la especificación y luego llamando a la especificación. O (alguna otra especificación). Básicamente, debes escribir tu propio árbol de expresiones un poco. Ejemplo de código y explicación aquí: http://codeinsanity.com/archive/2008/08/13/implementing-repository-and-specification-patterns-using-linq.aspx –
Tengo una pregunta estúpida, si estos registros se están adquiriendo de la base de datos, ¿estamos obteniendo todos los registros y luego filtrándolos en la memoria? Si es así, ¿cómo puedo pasar las condiciones a la base de datos –