score:1

Accepted answer

answering my own question...

after some experiments (including nick guerrera's original answer) i took another approach - instead of trying to reuse the expression i reuse the whole linq. however, it still required creating a container struct.

struct pair {
    public ione one { get; set; }
    public itwo two { get; set; }
    public pair(ione one, itwo two) : this() {
        one = one;
        two = two;
    }
}


public iqueryable<pair> get(isession s, int color) {
            return from one in s.query<ione>()
                   from two in s.query<itwo>()
                   where (one.id == two.oneid) && (two.color > color)
                   select new pair(one, two);
        }

now i can call

get(s, color).count();

and

var records = (from data in get(s, color) select data).take(2000);

etc.

score:1

first of all why do you have two tables with same set of fields? ideally database design should avoid same field names in different tables. design should use inheritance. common fields should move into base class and ef let's you create table per hierarchy, that should resolve your problem.

if you create your model with table per hierarchy then you will not need interface, and your linq queries can use shared filter expressions.

there is no way to achieve what you are asking unless you sit down and write a complex reflection based method that will clone your expression from one type to another type.

score:3

there may be a more elegant solution that escapes me at the moment, but you could just use tuple<ione, itwo> instead of the anonymous type:

static expression<func<tuple<ione, itwo>, bool>> mywhereexpression2(int color) {
    return t => (t.item1.id == t.item2.oneid) && (t.item2.color > color);
}

int color = 100;
iqueryable<ione> records = (from one in s.query<ione>()
                            from two in s.query<itwo>()
                            select tuple.create(one, two))
                            .where(mywhereexpression2(color))
                            .select(t => t.item1);

update: i probably answered too quickly above as that won't work with linq to sql since the call to tuple.create cannot be translated to sql. to work with linq to sql, the only solution i see at the moment is to create a named type:

class pair
{
    public ione one { get; set; }
    public itwo two { get; set; }
}

static expression<func<pair, bool>> mywhereexpression2(int color) {
    return p => (p.one.id == p.two.oneid) && (p.two.color > color);
}

int color = 100;
iqueryable<ione> records = (from one in s.query<ione>()
                            from two in s.query<itwo>()
                            select new pair { one = one, two = two })
                            .where(mywhereexpression2(color))
                            .select(p => p.one);

Related Query

More Query from same tag