2010-01-27 11 views
12

En mi LINQ a la instalación de SQL Tengo varias tablas que se asignan a las clases que básicamente apoyan la misma interfaz para apoyar el control de versiones, es decirHacer un predicado reutilizable para EntitySet <T>, IQueryable <T> y IEnumerable <T>

public interface IValid 
{ 
    int? validTo { get; } 
    int validFrom { get; } 
} 

El LINQ a SQL clases se derivan de esta interfaz como esta:

public partial class representationRevision : IValid 
{ 
} 

Ahora me gustaría definir un DRY (Do not Repeat Yourself) de filtrado de manera EntitySet<T>, IEnumerable<T> y IQueryable<T> para que las listas resultantes sean válidas para una revisión específica. He intentado hacer esto:

public static class ExtensionMethods 
{ 

    public static IQueryable<T> ValidFor<T>(this IQueryable<T> v, int? revision) 
     where T : IValid 
    { 
     return v.Where(cr => ((cr.validFrom <= revision) && 
      ((cr.validTo == null) || (cr.validTo > revision))) 
      || ((revision == null) && (cr.validTo == null)) 
      ); 
    } 
} 

Pero esto da problemas en EntitySet<T>. Agregué una implementación especial para EntitySet que primero llama a AsQueryable(), pero esto arroja una excepción. Sin inmutarse Intenté hacer un predicado por lo que podría utilizar el enfoque Where(predicate):

public static Expression<Func<contentRevision, bool>> IsValidFor(int? revision) 
    { 
     return ((cr) => ((cr.validFrom <= revision) && 
      ((cr.validTo == null) || (cr.validTo > revision))) 
      || ((revision == null) && (cr.validTo == null))); 
    } 

Cuando se utiliza con .Where<contentRevision>(IsValidFor(revision)) da errores como:

error 5 'System.Data.Linq.EntitySet' no se contiene una definición de 'dónde' y el mejor método de extensión de la sobrecarga
'System.Linq.Enumerable.Where (System.Collections.Generic.IEnumerable, System.Func)' tiene algunos argumentos no válidos

Tenga en cuenta que esto es incluso sin utilizar la interfaz IValid ... he estado tratando todo tipo de variaciones sobre este tema (como agregar el parámetro int), pero todos ellos parecen invariablemente al fracaso. ¿Alguna sugerencia para llevarme en la dirección correcta?

+0

En su función de expresión estática anterior, el primer parámetro de tipo es 'contentRevision', ¿eso es un error tipográfico? Esperaría que fuera 'IValid'. Además, el error que muestra en la parte inferior parece ser el resultado de pasar un predicado con 3 parámetros de tipo. ¿Qué sucede si pasa el predicado como se muestra ('Expresión >')? Lo he usado mucho y funciona bien, no puedo entender por qué tu código no compilará. –

+0

Está en el comentario debajo del código "Tenga en cuenta que esto es incluso sin utilizar la interfaz IValid".Básicamente traté de hacerlo funcionar sin utilizar IValid primero, pero por el momento no hay diferencia en el comportamiento. Creo que es algo específicamente que hacer con EntitySet : si reescribo mi código para hacer uniones de tabla todo parece funcionar bien. –

Respuesta

4

No estoy seguro de EntitySet<T> por lo que se centrará en IQueryable<T> y IEnumerable<T>.

Para permitir que el proveedor de LINQ evalúe los árboles de expresión que IQueryable<T> usa para sus argumentos de expresión, es necesario asegurarse de que se preserve la interfaz subyacente. De lo contrario, haga todo en el término IEnumerable<T> (es decir, si puede arrastrar todo el conjunto de datos a la memoria local y luego procesarlo allí, en lugar de hacerlo en la base de datos, simplemente use LINQ para objetos).

La otra opción es el método AsQueryable extensión (parte de Queryable clase) que convierte un IEnumerable<T> a un IQueryable<T>, y luego se puede compartir el resto del código.

IQueryable<T> SomeSharedQuery(this IQueryable<T> source) { 
    return source.(LINQ query operators...); 
} 
IQueryable<T> SomeSharedQuery(this IEnumerable<T> source) { 
    return source.AsQueryable().SomeSharedQuery(); 
} 

Tiene el código compartido, con un método de adaptador.

+1

Eso funciona de manera brillante, pero no para EntitySet embargo. El AsQueryable() no tiene una traducción a SQL (por extraño que parezca). –

+0

@Matthijs: Bawed en los documentos 'EntitySet ' implementa 'IEnumerable ' por lo que obtendrá una coincidencia. Dado 'EntitySet ' se trata de la carga diferida de partes de una consulta existente que no obtiene nada de una implementación 'IQueryable ' en él ... si desea que el DB haga el trabajo a través de la asociación incluya eso en el original consulta. – Richard

+0

¿De qué manera no funciona para 'EntitySet '? – svick

Cuestiones relacionadas