2011-03-14 20 views
5

Me gustaría generar dinámicamente predicados que abarquen varias tablas en una unión en una instrucción Linq. En el siguiente fragmento de código, quiero usar PredicateBuilder o una construcción similar a reemplazar el 'dónde' declaración en el siguiente código:¿Puede PredicateBuilder generar predicados que abarquen varias tablas?

Reemplazar:

public class Foo 
{ 
    public int FooId; // PK 
    public string Name; 
} 

public class Bar 
{ 
    public int BarId; // PK 
    public string Description; 
    public int FooId; // FK to Foo.PK 
} 

void Test() 
{ 
    IQueryable<Foo> fooQuery = null; // Stubbed out 
    IQueryable<Bar> barQuery = null; // Stubbed out 

    IQueryable<Foo> query = 
     from foo in fooQuery 
     join bar in barQuery on foo.FooId equals bar.FooId 
     where ((bar.Description == "barstring") || (foo.Name == "fooname")) 
     select foo; 
} 

con algo como:

void Test(bool searchName, bool searchDescription) 
{ 
    IQueryable<Foo> fooQuery = null; // Stubbed out 
    IQueryable<Bar> barQuery = null; // Stubbed out 

    IQueryable<Foo> query = 
     from foo in fooQuery 
     join bar in barQuery on foo.FooId equals bar.FooId 
     select foo; 

    // OR THIS 

    var query = 
     from foo in fooQuery 
     join bar in barQuery on foo.FooId equals bar.FooId 
     select new {foo, bar}; 

    var predicate = PredicateBuilder.False<Foo>(); 
    if (searchName) 
    { 
     predicate = predicate.Or(foo => foo.Name == "fooname"); 
    } 
    if (searchDescription) 
    { 
     // Cannot compile 
     predicate = predicate.Or(bar => bar.Description == "barstring"); 
    } 
    // Cannot compile 
    query = query.Where(predicate); 
} 

¿Algún pensamiento, idea, estrategia para abordar este problema?

Gracias,

EulerOperator

Respuesta

6

Creo que su problema es con el tipo T de su PredicateBuilder - la mitad de su predicado en caso de actuar en un Foo, la otra mitad está en una barra.

podría reemplazar esto con un simple consulta construida manualmente:

void Test() 
{ 
    IQueryable<Foo> fooQuery = null; // Stubbed out 
    IQueryable<Bar> barQuery = null; // Stubbed out 

    IQueryable<Foo> query = 
     from foo in fooQuery 
     join bar in barQuery on foo.FooId equals bar.FooId 
     select new {Foo = foo, Bar = bar}; 

    if (searchName) 
    { 
     query = query.Where(fb => fb.Foo.Name == "fooname"); 
    } 
    if (searchDescription) 
    { 
     query = query.Where(fb => fb.Bar.Description == "barstring"); 
    } 

    // use query here 
} 

Un método alternativo es utilizar PredicateBuilder pero para que funcione en el Foo, Bar pareja - por ejemplo,

class FooBar 
{ 
    public Foo Foo {get;set;} 
    public Bar Bar {get;set;} 
} 

void Test(bool searchName, bool searchDescription) 
{ 
    IQueryable<Foo> fooQuery = null; // Stubbed out 
    IQueryable<Bar> barQuery = null; // Stubbed out 

    var query = 
     from foo in fooQuery 
     join bar in barQuery on foo.FooId equals bar.FooId 
     select new FooBar 
     { 
      Foo = foo, 
      Bar = bar 
     }; 

    var predicate = PredicateBuilder.False<FooBar>(); 
    if (searchName) 
    { 
     predicate = predicate.Or(foobar => foobar.Foo.Name == "fooname"); 
    } 
    if (searchDescription) 
    { 
     predicate = predicate.Or(foobar => foobar.Bar.Description == "barstring"); 
    } 
    query = query.Where(predicate); 

    // use query here 
} 
Cuestiones relacionadas