2010-08-19 7 views
6

Me gustaría devolver un conjunto de entidades que tiene una ID y que está contenida en una lista o matriz de ID utilizando LINQ y Servicios de datos. Sé cómo usar LinqToEF, pero no sé cómo hacerlo con los servicios de datos o con las convenciones de consulta de OData.Seleccionar entidades donde ID en matriz int - Servicios de datos WCF, LINQ

Mi pensamiento es que me gustaría hacer algo como:

int[] intArray = {321456, 321355, 218994, 189232}; 
var query = (from data in context.Entity 
      where intArray.contains(data.ID) 
      select data); 

¿Hay alguna manera de lograr el uso de los servicios de datos/OData? Sé que probablemente podría piratearlo con una Operación de Servicio, pero preferiría no hacerlo.

Saludos.

Respuesta

8

Actualmente OData (el protocolo subyacente) no admite la operación Contiene. Es por eso que la biblioteca del cliente no traduce la consulta anterior. Las personas básicamente usan dos formas de superar esta limitación: 1) Use las operaciones de servicio como anotó. 2) Construya una cláusula where de forma dinámica que usa comparaciones simples para comparar el valor de cada elemento del conjunto. Entonces, si la matriz contiene 1, 2, 3, donde sería data.ID == 1 || data.ID == 2 || data.ID == 3 La solución n. ° 2 es agradable porque es un cambio solo del lado del cliente. La desventaja es que solo funciona en arreglos pequeños. Si la matriz contiene demasiados elementos, la expresión se alarga demasiado y eso genera todo tipo de problemas. La solución n. ° 1 no tiene el problema de tamaño, pero debe proporcionar la operación en el servidor.

+0

"Construir una cláusula Where donde se usan comparaciones simples dinámicamente para comparar el valor de cada elemento de la matriz "- puede dar un ejemplo. –

+0

El ejemplo sería bastante largo: probablemente pueda buscar "LINQ dinámico" y tal. La forma de bajo nivel es usar la clase Expression y su API para construir la consulta LINQ programáticamente. –

0

Gracias los hombres que realmente me ayudó :) :)

lo hice como Vitek dijo Karas.

1) Descargar la consulta dinámica biblioteca Marque esta link

No hay necesidad de leerlo sólo tiene que descargar la biblioteca de consultas dinámico

2) Comprobar el proyecto llamado DynamicQuery. En él encontrarás una clase llamada Dynamic.cs. Cópielo en su proyecto

3) Genere su proyecto (Si utiliza Silverlight, aparecerá un error que indica que ReaderWriterLock no se encuentra. No se asuste. Simplemente comente o elimine las líneas que generan errores (solo hay 6 o 7 líneas que hacen errores))

4) Todo hecho sólo necesita ahora para escribir su consulta Ejemplo: ordersContext.CLIENTS.Where(" NUMCLI > 200 || NUMCLI < 20");

Todo hecho. Si tiene que usar el método 'Contiene' solo escriba un método que itere sobre su matriz y devuelva la cadena que utilizará su solicitud.

private string MyFilter() 
{ string st = ""; 

     foreach(var element in myTab) 
     { 
       st = st + "ThePropertyInTheTable =" + element + "||"; 
     } 

     return st; 
} 

espero que me entienden y que ayudé a alguien :)

+0

Esta solución genera un problema cuando la solicitud era demasiado larga. Así que encontré otra solución usando AddQueryOption y usando $ filter como este: DataServiceQuery ordersQuery = (DataServiceQuery ) this.context.CLIENTS.AddQueryOption ("$ filter", MyFilter()); – ihebiheb

+0

No use la mayúscula AND. conduce a un error usa y no AND. – ihebiheb

3

Aquí es mi realización de la que() Método para filtrar colección IQueryable por un conjunto de entidades seleccionadas:

public static IQueryable<T> WhereIn<T,TProp>(this IQueryable<T> source, Expression<Func<T,TProp>> memberExpr, IEnumerable<TProp> values) where T : class 
    { 
     Expression predicate = null; 
     ParameterExpression param = Expression.Parameter(typeof(T), "t"); 

     bool IsFirst = true; 

     // Create a comparison for each value eg:     
     // IN: t => t.Id == 1 | t.Id == 2     

     MemberExpression me = (MemberExpression) memberExpr.Body; 
     foreach (TProp val in values) 
     { 
      ConstantExpression ce = Expression.Constant(val); 


      Expression comparison = Expression.Equal(me, ce); 

      if (IsFirst) 
      { 
       predicate = comparison; 
       IsFirst = false; 
      } 
      else 
      { 
       predicate = Expression.Or(predicate, comparison); 
      } 
     } 

     return predicate != null 
      ? source.Where(Expression.Lambda<Func<T, bool>>(predicate, param)).AsQueryable<T>() 
      : source; 
    } 

Y la llamada de este método se ve así:

IQueryable<Product> q = context.Products.ToList(); 

var SelectedProducts = new List<Product> 
{ 
    new Product{Id=23}, 
    new Product{Id=56} 
}; 
... 
// Collecting set of product id's  
var selectedProductsIds = SelectedProducts.Select(p => p.Id).ToList(); 

// Filtering products 
q = q.WhereIn(c => c.Product.Id, selectedProductsIds); 
+2

Muy agradable. Sin embargo, da un resultado inesperado con una matriz vacía como entrada. No esperarías que haya nada en esa matriz vacía que no genere resultados, sino que devuelve todo. Con esto en mente, he cambiado la declaración de devolución a: return predicate! = Null ? source.Where (Expression.Lambda > (predicate, param)). AsQueryable () : source.Where (x => false) .AsQueryable (); –

Cuestiones relacionadas