Quiero decir, una búsqueda del tipo
from a in a where criterio select a
La idea es que criterio se pueda contruir dinámicamente dependiendo de si los campos de un formulario han sido rellenados.
criterio = ( a.Nombre == textboxNombre.value && a.telefono == textboxApellidos.value)
pero no incluya a.apellidos si el textbox se dejó vacio.
Por lo que sé sería algo como:
var gquery = from a in repositorio.Humanos
select a;
gquery.Where = .....una expresion lambda ???
List<humanos> listaDeResultados = gquery.ToList();
Pero lo que no tengo claro es como editar gquery.Where
No se podría tratar como un simple string???
Me podrían dejar algún ejemplo del uso de "Predicate"
Muchas gracias!!
Mmmmm parece que Linq Dynamic Library permite precisamente eso:
using System.Linq.Dynamic;
NorthwindDataContext northwind = new NorthwindDataContext();
var query = northwind.Products
.Where("CategoryID = 3 AND UnitPrice > 3")
.OrderBy("SupplierID");
GridView1.DataSource = query;
GridView1.DataBind();
Pero no consigo descargarla. ALguien conoce el linq o puede dejarme la .dll?
Hola Gonzalo, esto hace un tiempo lo había preguntado por twitter. No encontraba la forma de hacer linq dinámicos, en mi caso yo necesitaba ordenar los resultados por algún criterio enviado por parámetro.
Mi solución es a lo bestia, usando switch pero de esta manera se repite mucho código. La solución mas optima es como tu dices con Linq dinámico.
Para descargar las librerías de LINQ Dynamic Query Library:
Gracias Fabian, ya había encontrado la librería. Mi problema era que no sabía usarla!! parece que no existe la dll!!
Hay que descargarse el fichero zip desde el link:
http://www.scottgu.com/blogposts/dynquery/dynamiclinqcsharp.zip
O desde el que Fabian ha dejado en la respuesta anterior. El fichero contiene un proyecto de ejemplo. Del código de dicho proyecto tienes que copiar la clase DynamicLibrary.cs e incluirla dentro de tu propio proyecto.(Cuidado de no cambiar el namespace)
Apartir de ese momento puedes referenciar
using System.Linq.Dynamic;
Después al compilar muy probablemente recibirás el siguiente error (yo al menos lo recibí):
Error 1 Missing compiler required member 'System.Runtime.CompilerServices.ExtensionAttribute..ctor'
La nueva clase necesita de ExtensionAttribute.El compilador lo busca en el namespace System.Runtime.CompilerServices que se encuentra System.Core.dll. Las versiones 2.0 y 3.5 de esta dll son diferentes. Así que dependiendo de donde la cojas puedes encontrar problemas. Mi proyecto ya tenía una referencia a Core.dll y aun así recibí el error. Lo que averigué es que realmente so se necesita la dll entera. Sólo la clase ExtensionAttribute y, puedes escribirla tu mismo. Yo tuve que incluir la siguiente clase:
namespace System.Runtime.CompilerServices
{
[AttributeUsage(
AttributeTargets.Assembly
|AttributeTargets.Class
|AttributeTargets.Method,
Inherited=false,
AllowMultiple=false)
]
public class ExtensionAttribute : Attribute
{
}
}
Después de eso todo funcionó perfectamente. Pude hacer consultas del tipo:
public IList<Domain.Membership> GetMembershipsByActivation(bool activated, bool approved)
{
string clause = "IsActive = @0 AND IsApproved = @1";
return (Memberships.Where(clause,activated, approved)).ToList();
}
Como véis, acepta una cadena como cláusula where y permite la referencia a parámetros con arroba @0,@1,.......
Perfecto!!
Fabian;
No se si la pregunta tenga alguna relacion directa con nHibernate, pero segun loo que he visto Linq para nHibernate tiene algunas limitaciones para realizar queries complejas, no soporta cuestiones como agregacion, subqueries y otras mas que se publicaron el el "release" de la version 1.0 de NHibernate Linq.
Yo en mi caso uso Linq para consultas sencillas y directas, para consultas mas complejas y donde el predicado puede ser dinamico, mejor uso directamente Criteria o HQL, esto me permite explotar NHibernate de buena manera.
Ok, acabo de descubrir otra forma bastante eficaz de hacer esto mismo sin recurrir a Dynamic LINQ.
Pensándolo un poco me he dado cuenta de que la cláusula WHERE de Linq simplemente tiene que evaluar un booleano, podemos entonces hacer algo como:
public List<Guid> GetProfileUserIDsByCriteria(string outletId, string customerId, string agreementNo)
{
return (from m in Memberships
where ((!string.IsNullOrEmpty(outletId)) ? m.Agreement.OutletID == outletId: true)
&& ((!string.IsNullOrEmpty(customerId)) ? m.Agreement.CustomerID == customerId : true)
&& ((!string.IsNullOrEmpty(agreementNo)) ? m.Agreement.AgreementNo.EndsWith(agreementNo): true)
select m.UserObjectId).ToList();
}
De esta forma nos ahorramos los problemas de cargar Dynamic LINQ, y de construir las cadenas con string builder que es verdad que queda un poco feo.
A mi me ha convencido.
Saludos
Les cuento mi situación, y luego les muestro un código que escribí hace unos días. Yo tenía un objeto filter que tenía los siguientes campos :
- PropertyInfo del tipo PropertyInfo
- Value del tipo Object
- Operator un enumerable que van a ver que tiene luego.
Con eso tenía que armar una expression lambda para filtrar un IQueryable.
Lo primero que intente hacer fue armar un string y hacerlo con dynamic linq, pero luego me puse a investigar y salio esto:
var parameterExpression = Expression.Parameter(typeof(TEntity), "p");
var propertyValue = Expression.Property(parameter, filter.PropertyInfo);
var value = Expression.Constant(filter.Value);
Expression body = null;
if (filter.Operator == OperatorHelper.IsEqualTo)
{
body = Expression.Equal(propertyValue, value);
}
if (filter.Operator == OperatorHelper.StartsWith)
{
body = Expression.Call(propertyValue, "StartsWith", new Type[] { }, value
}
if (filter.Operator == OperatorHelper.Contains)
{
body = Expression.Call(propertyValue, "Contains", new Type[] { }, value);
}
if (filter.Operator == OperatorHelper.GreaterOrEqualsThan)
{
body = Expression.GreaterThanOrEqual(propertyValue, value);
}
if (filter.Operator == OperatorHelper.LessThan)
{
body = Expression.LessThan(propertyValue, value);
}
if (filter.Operator == OperatorHelper.LessOrEqualsThan)
{
body = Expression.LessThanOrEqual(propertyValue, value);
}
if (filter.Operator == OperatorHelper.IsNull)
{
var nullValue = Expression.Constant(null, filter.PropertyType);
body = Expression.Equal(propertyValue, nullValue);
}
if (filter.Operator == OperatorHelper.IsNotNull)
{
var nullValue = Expression.Constant(null, filter.PropertyType);
body = Expression.NotEqual(propertyValue, nullValue);
}
if (filter.Operator == OperatorHelper.InList)
{
throw new NotImplementedException();
}
if (body == null)
throw new NotImplementedException();
return source.Where(Expression.Lambda<Func<TEntity, bool>>(body, parameter));
Tu Respuesta
YoProgramo.NET es una comunidad para unir y ayudar a los programadores hispanos.
Aquí los desarrolladores pueden encontrar repuesta a sus dudas y colaborar con los demás, compartiendo sus conocimientos y experiencia.