2011-11-17 13 views
5

Estoy trabajando en una aplicación grande que está usando Dynamic LINQ Library para filtrar.Filtrado en subconsultas usando Dynamic LINQ

Todas las clases de mis datos de acceso capas se derivan de un DALAncestor ancestro común que, entre otras cosas, define el método GetData: Lista abstracta GetData (filtro Filtro) pública

Una implementación de este método para un cliente se vería así (simplificado):

public override List<Entities.Customer> GetData(Filter filter) { 
    var customers = from c in db.Customers 
        select new Entites.Customer { 
        ID = c.ID, 
        FullName = c.Name, 
        Country = c.Country 
        }; 

    return = filter.Apply(customers).ToList(); 
} 

"Aplicar" es un método que toma un conjunto de condiciones y se aplica a todos ellos utilizando LINQ dinámica Libary.

método GetData se llama así:

private void DemoCallGetDataMethod() { 
    var filter = new Filter(); 
    filter.AddCondition("Country", "Austria"); 

    var list = myCustomerDAL.GetData(filter); 
    // do something 
} 

SQL Server consigue un selecto DECLARACIÓN:

SELECT [t0].ID, [t0].Name, [t0].Country 
    FROM Customer [t0] 
WHERE [t0].Country = @p0 

(@ P0 es un parámetro con su valor establecido en "Austria").

Todo funciona muy bien, si quiero filtrar valores solo en el nivel "superior" (principal). Sin embargo, dado que construyo mi filtro en la entrada del usuario en el formulario de filtro, hay casos en los que los usuarios quieren filtrar por un valor en detalle (es decir, las columnas para filtrar se conocen solo después de que un usuario hace clic en "Buscar").

No encuentro una solución para esto: "Consigue todos los clientes de Austria que compraron Pepsi".

He intentado varias cosas, ninguna de ellas parece estar funcionando. La idea básica es:
1. Add support for CONTAINS a DynamicLibrary
2. cambiar el código para

public override List<Entities.Customer> GetData(Filter filter) { 
    var customers = from c in db.Customers 
        select new Entites.Customer { 
        ID = c.ID, 
        FullName = c.Name, 
        Country = c.Country, 
        Items = c.Order.SelectMany(o => o.Item).Select(i => i.ItemId).ToList() 
        }; 

    return = filter.Apply(customers).ToList(); 
} 

private void DemoCallGetDataMethod() { 
    var filter = new Filter(); 
    filter.AddCondition("Country","=", "Austria"); 
    filter.AddCondition("Items","Contains", "11"); // 11 = Id for Pepsi 

    var list = myCustomerDAL.GetData(filter); 

    // do something 
} 

la exepction lanzado es:

System.InvalidOperationException: Ningún método genérico 'Contiene' en tipo 'System.Linq.Enumerable' es compatible con los argumentos y argumentos de tipo suministrados. No se deben proporcionar argumentos de tipo si el método no es genérico.

¿Alguien tiene alguna idea de lo que estoy haciendo mal? ¿O estoy yendo en la dirección equivocada y debería intentar otro enfoque? ¿Cual? :)

EDITADO: cambió mi ejemplo

+0

Lo sentimos Iam no está seguro de lo que está después, el artículo que usted ha mencionado también ha proporcionado una respuesta al mismo problema que está enfrentando para evitar esa excepción. ¿Y porque quieres seguir esa ruta, realmente no entiendo lo que estás buscando :)? – user182630

+0

filter.AddCondition ("Artículos", "Contiene", "Pepsi"); - Esto solo funciona para String and String, no List y string – Tsabo

+0

@ user182630 Quiero poder filtrar por valores de subselects en general, no solo para un caso específico. El enfoque de ese artículo solo funciona si usted codifica sus filtros, lo cual no es algo que yo pueda hacer. –

Respuesta

2

@ user182630 Quiero ser capaz de filtrar por valores de subselects en general, no sólo para un caso específico. El enfoque de ese artículo funciona solo si codifica sus filtros, lo que no puedo hacer do. - hace 9 minutos Marko Juvančič

tener una lectura a través de este artículo http://csharpindepth.com/articles/chapter5/closures.aspx

2

utilizo PredicateBuilder para consultas dinámicas en mis aplicaciones.

Predicate Builder

En su caso me imagino que será algo como:

string MyCountry = "Austria"; 
string MyProductId = 11 

var Predicate = PredicateBuilder.True<db.Customers>(); 
Predicate = Predicate.And(p=>p.Country ==MyCountry && p.Order.SelectMany(o=>o.Item).Where(i=>i.id == 11).Count() >0); 

var list = Customers.Where(Predicate).Select(s=>s).ToList(); 
+0

Este enfoque falla en el requisito de "las columnas deben filtrarse por conocerse solo después de que un usuario haga clic en Buscar". –

+0

Bueno, si todas las columnas se conocen de antemano, entonces esto no es un problema. – Tsabo

+0

No lo son. Método El filtro "Aplicar" no sabe nada sobre las columnas. –